'''
UNIT INFO (MODULE)
The module has a framework level, meaning that this framework is usable in
different applications. Also there is an app-level, meaning that sametimeally
a specific app is developped, namely PyKnow. It is being tried to separate as
much as possible the generic and specific code.

---framework level---
This module implements the auimanager-framework of wxpython. The aui-framework
consists of dockable windows, menu's and toolbars. All of these are defined in
 the module defgui; there, the different properties can be set.
For the windows/controls, the module genFrames is used (generic frames),
in which the controls for a window-pane are dynamically generated based on a
definition.

Belonging modules:
-main_startup (formerly known as 'auiFramework'); GUI layer on window level - template (half-generic)
-genFrames; GUI layer on control level - generic
-jodb; database-connection and SQL-functions - generic
    - ? rename to dbsql?
-defgui; gui-definition module - app-specific
-jotools; divers tools - generic
-knob_logic; application-logic-layer, recursive and manipulation functions - app-specific
Upcoming modules:
-db_logic;  data-logic layer (ex. newIdNumber; generic db-functions) - generic
Inconclusive modules:
-db_generalize; makes the db-interface generic for db-types; much work, small benefits
-db2gui; would give mappings for type-conversion of specific backends; might be
done in main_startup or genframes.

Configuration-file:
-to store some local stuff you don't want in the DB (future)

---Application level---
-navigator-panel
-listpanels left and right
To be worked out...

-----------------------ADAPTATIONS----------------

ADAP HIS
- relations query vrs_1.1_his
    -add panels and pane and pre-hide them, using the layout
    -layout
        -generic list-pane overlaps navpanel and left-right list (mainListPanel)
        -list-control-panel overlaps treeview
        -modPanel stays where it is
    - make interface switch between panels
    (hide and show the relevant panels)
        -create menu-items
            -create perspectives, that is
            hide or show sets of panes
                -example in wx10dokbareraampjes
                -positively define perspectives in defgui
                    -use a baseset and extra sets
    -create toolbar-buttons to switch configs
- bugs (if > elif):
    -msLongtext
    -search fails
- tree-left; load tree-items from lefthand side
-tree-view upgrade
    -sync to modpanel
-exchange stuff; list the todoos:
    v-parametrize functions
    v-bring them over to thruport
    v-create new button
    v-create a batch-function
    -write down the mobile editors
        -notepad or pocketnotepad from tillanosoft.com
        -pockettexteditor from kutinsoft
    -add change=xp to favorites-list
    -after import import-file:
        -backup latest file
        -create new one and auto-fill import-file with the headers
-make the icons genericly accessible
    -use sys.arg or so to get the path to the icons
    -test if the path is ok
    -else take the provided path and test it
    -else do not load the toolbar and give a message of the situation
-generalize menulint versus toolbarlint functions
-tree-view upgrade
    -seek an object in the tree (expand the tree from current object to the
    sought object)
        v-adapt readBrancheToTable
            v-Make readbranche two-directional
            v-add Sortpath of RelIDs to longtext so you get the treepath
            v-make function to create a table from the relIDs in de longtext
            of the temptable for the tree to query
                v-create the table in the database
        -adapt treeview
            v-put button on navpanel
            v-tree-re-coding
-create function jodb.readDictFromParams for single records
-parameter screen
    -create function readOption in knob_logic
-redesign a single thruports-dialog
-migrate to open source-database (sqlite has been chosen over firebird)
-add file-management
    v-start minimal gui (without db)
        v-functionalize and parametrize init-code
    v-close db
        v-research the possib to remove or disable
            v-menu-bar-items > disable
            v-toolbar-items > disable
        v-find new icons
        v-study loading-order; db-using panes cant be loaded without db
            -forbid initial db-usage and (re)load data on open db
                -remove data-loading from addDynamicPanes and addSpecificPanes,
                and isolate it in loadAllDbData
        v-add to menu and toolbar
    v-test initial db-independance by renaming the db; ok
    v-open any db
        v-research open-dialog
        v-set the db
        v-set the messages on the statusbar
    v-info on db
        -show type and full name of db
    -new db; copy a template.db
        v-update backup-function
        v-call-code
            v-copy template
            v-reload database
    v-disable recent-button
-bring over the data from ms access to sqlite;
    -create direct data-pump between dbs
-re-import data to sqlite and go to production on sqlite
-temporaryly disable with import- and export-screens
-add about screen
    -think of versioning-model
    -?rename auiframework.py to knobjex_main or main_startup.py
        -choose the latter to keep a generic app-name
-adapt 'where-am-i'-code to generic code
    -describe current situation
        -using sysarg to determine the current dir
        -works only (using remote engine) when:
            -script handling not yet returned to engine, so
            it is needy to query modulepathst and put it in a
            variable
    -update sysarg-check for main file-part
        -create general functions and globar var
            -replace local sysarg-uses
-on startup: test db-version and conditionally open upgrade-screen
    v-introduce param minimaldatabaseversionfl
    v-copy template.db and rename it to new target (blabla_upgraded_to_2.02)
        v-make function copyFile
        v-test it!
    v-open import-tool and prepopulate db-fields and customize the
    message
        -add parameters to the importDialog
v-enable panel-shrinking
    v-remove minimal size of tree-pane
-consider adding a parameter 'db' to the db-functions
    v-migrate jodb to pardb, being a db-specific module
    v-make pardb.py
-upgrade current option-screen
-create new environment-db with table sysparams
    v-add icons
-improve panel-sizing
    -store window-sets in a database
        v-pre-add window-sets
        -enable write to database
-create generic export and import of text-files
    -create export-dialog
    -create import-dialog

ADAP NO


ADAP FUT
-isolate pyodbc-dependency to db_species
-test 'where-am-i'-code to generic code
    -if not working create test for trying to get the modulepath
        -use places.py for alternative methods
            -improve testing-scripts
            -cases
                -from indirect and different engines
                -from executable
-create query for 'end-items' ??
-check every start-up-code according to http://wxpython.org/tut-part1.php
-file-management
    -iniconfig:
        -open default or recent db from iniconfig.txt
        -open default with knobjex_sqlite.db if no config-file says otherwise
- tooltips vrs_1.2
- speedup-options:
    -speed up combo-loading
- info-log-panel vrs_1.2
    (optimally it would be a table with all the changes, with
    fields like: time, source, tipOrResult, info)
-enable unicode
- synchronization:
    -table synchronizations, with fields:
        -db1, db2, sync-date
    -timestampfields on record-level:
        - CreationTimeStamp (cts)
        - LatestTimeStamp or moddate(lts)
    -table PreSyncAnalysis, records are analyzed and result added to table,
    which has the fields:
        -db1_relid, db2_relid, status
        -former sync date (sd)
        -status can be:
            -equal (lts equal)
            -updated1 (lts1 > lts2 = sd),
            -updated2 (lts2 > lts1 = sd)
            -partially inconclusive (sd <> lts1 <> lts2 <> sd),
            both changed since sync.
            -new (single cts > sd)
            -deleted (single cts < sd)
-add repeating events-dialog
    - prefill calendar-table
        -create cal-table

Bugs:
-wxpython 2.8.6 appears not to work, possibly because of:
    - cyclische ref: import main_startup
    - problems with the toolbar accessing non-existing icon-files
    * test on other laptop
'''


import wx
import wx.aui
import os
import sys
from datetime import datetime
import jotools
import defgui   # **specific**
import pardb
import lisco
import treeco
import db_species
##import pyodbc

import genFrames
import main_startup     # can this be done differently? seems dirty to me
                        # this reinitializes also global variables?
import knob_logic
import thruport
import pumpupdabase
import pysqlite2    # necessary for error-names
import os_species
import emailthis
import globala


##moduli = []
##for modulst in defgui.defImports:
##    moduli.append(__import__(modulst))

##sys.py3kwarning = True


defPaneli = defgui.defPaneli
defImports = defgui.defImports
defDatadi = defgui.defDatadi
defDialogdi = defgui.defDialogdi

hisli = []

datest = str(datetime.today())[:10]
datetimest = str(datetime.today())[:19]
isotu =datetime.isocalendar(datetime.today())

isocalendarst = 'year: ' + str(isotu[0]) + \
            ',   week: ' + str(isotu[1]) + \
            ',   day: ' + defgui.weekdaysdi[isotu[2]] + \
            '                  (date: ' + datest + ')'

globalmodulepathst = ''

codeversionfl = 2.80
minimaldatabaseversionfl = 102.80


def setCurModulePath():
    '''
    UNIT INFO:
    Only called once on startup! when needing the module-path use
    the variable 'globalmodulepathst'; after startup secondary
    interpreter-engines can alter the outcome.
    '''
    global globalmodulepathst   # 'global' for write-access to global
    basenamest = os.path.basename(str(sys.argv[0]))
    (shortnamest, extensionst) = os.path.splitext(basenamest)
    if shortnamest == 'main_startup':
        globalmodulepathst = os.path.dirname(str(sys.argv[0]))
    else:
        print 'Could not set module-path!'


def curModuleSubDir(subdirst):
    subdirpathst = os.path.join(globalmodulepathst, subdirst)
    return subdirpathst

def removeSpaces(stringWithSpaces):
    return stringWithSpaces.replace(" ","")

def printBarItems(st='m'):
    if st == 'm':
        defBarli = defMenuli
        indexit = 1
        baseit = 100
    else:
        defBarli = defToolbarli
        indexit = 0
        baseit = 1000

    for barli in defBarli:
        it = defBarli.index(barli)
        for itemli in barli[1]:
            if itemli[0] == 'AppendSeparator':
                pass
            else:
                subit = barli[1].index(itemli)
                idit = ((it + 1) * baseit) + subit
                print str(idit) + '   ' + itemli[indexit]

def fillComboData(combobox, *args):
    '''
    Fill the combo-items with data from query created from the arguments
    example:
    fillComboData(self.ctrldi['cboSource'],'FDQ_SOURCES_GROUPED',['Source'])

    ADAP FUT
    -use combobox.appenditems to append an entire list at once; see
    experimental version
    '''

    getattr(combobox,"Clear")()
    datali = pardb.readFromParams('', *args)
    for row in datali:
        getattr(combobox,"Append")(str(row[0]))
##    combobox.SetSelection(0)

def fillComboDataGrouped(combobox, *args):
    '''
    xxx
    '''

    getattr(combobox,"Clear")()
    datali = pardb.readGroupsFromParams('', *args)
    for row in datali:
        getattr(combobox,"Append")(str(row[0]))
##    combobox.SetSelection(0)

def fillComboDataExperimental(combobox, *args):
    '''
    Fill the combo-items with data from query created from the arguments
    example:
    fillComboData(self.ctrldi['cboSource'],'FDQ_SOURCES_GROUPED',['Source'])

    -use combobox.appenditems to append an entire list at once
    '''
    itemli = []
    getattr(combobox,"Clear")()
    datali = pardb.readFromParams('', *args)
    for row in datali:
        for val in row:
            itemli.append(str(val))
    getattr(combobox,"AppendItems")(itemli)

def showMessage(parent=None , messagest='', captionst='Message box',
                  stylit= wx.OK|wx.CENTRE|wx.ICON_INFORMATION ,
                  posit =wx.DefaultPosition ):

    '''
    -seems to work
        -test it on call from different sources
    -call like: showMessage(self, messagest, 'Database-info')

    ADAP FUT
    work out style-linked settings
    '''

##    wx.YES_NO | wx.ICON_QUESTION
##    wx.OK | wx.ICON_EXCLAMATION
##    wx.OK | wx.ICON_ERROR

    msg = wx.MessageDialog(parent, messagest,captionst, stylit)
    msg.ShowModal()
    msg.Destroy()

    # wx.YES_NO | wx.NO_DEFAULT | wx.CANCEL | wx.ICON_INFORMATION

def messageDialog(parent=None, message='', title='Message box',
                  style= wx.OK|wx.CANCEL| wx.CENTRE | wx.ICON_QUESTION,
                  pos=wx.DefaultPosition):
    """
    UNIT INFO:
    Message dialog wrapper function with a result returned.
    Use wx.ID_OK (beware the 'ID_' part) for wx.OK
    Call like:
    if messageDialog(self, 'message', 'caption') == wx.ID_OK:
    """
    dialog = wx.MessageDialog(parent, message, title, style, pos)
    result = dialog.ShowModal()
    dialog.Destroy()
    return result



class PyAUIFrame(wx.Frame):
    '''genericly implementable aui-framework working together with
    the modules: genframes, defgui and pardb (and some standard modules)'''

    def __init__(self, parent, ID=-1, title="", pos=wx.DefaultPosition,
            size=wx.DefaultSize, style=wx.DEFAULT_FRAME_STYLE |
                                         wx.SUNKEN_BORDER |
                                         wx.CLIP_CHILDREN):

        wx.Frame.__init__(self, parent, ID, title, pos, size, style)

        # set global module-path and operating-system
        setCurModulePath()
        os_species.setCurOperatingSystem()

##        showMessage(self, globalmodulepathst, 'module-path')

        # set global settings-database
        datadirst = curModuleSubDir('database')
        db_species.settingsdbst =  os.path.join(datadirst,'settings_kjx.db')
        if not db_species.testConnectSqlite(db_species.settingsdbst):
            messagest = 'The program-settings-database can not be found or is invalid ' + \
                '(file may be empty). ' + \
                '[settings_kjx.db].\nProgram can not continue and may hang! \n' + \
                'Place this valid db under knobjex/database and retry..\n\n' + \
                'Expected path:\n' + db_species.settingsdbst 
               
            showMessage(self,  messagest, 'No valid settings-db',  wx.ICON_ERROR)
##            self.Destroy()
            

        # set font-size-correction
        genFrames.pointcorrectionit = knob_logic.readOption('font_size_correction','sys')

        # set frame-icon
        iconsfolderst = curModuleSubDir('icons')
        iconfilest =  os.path.join(iconsfolderst,'kjx_logo.ico')
        icon1 = wx.Icon(iconfilest, wx.BITMAP_TYPE_ICO)
        self.SetIcon(icon1)

        # manager aanmaken
        self._mgr = wx.aui.AuiManager()
        self._mgr.SetManagedWindow(self)

        self._configs = []
        self.n = 0
        self.x = 0

        self.addStatusBar()
        # eigen windows-bemeting
        self.SetMinSize(wx.Size(400, 300))

        self.addMenuBar(defgui.defMenuli)
        self.addToolbars(defgui.defToolbarli)
        self.addDynamicPanes()
        self.addSpecificPanes()

        self.loadDatabase()

        self.Bind(wx.EVT_ERASE_BACKGROUND, self.OnEraseBackground)
        self.Bind(wx.EVT_SIZE, self.OnSize)
        self.Bind(wx.EVT_CLOSE, self.OnClose)


    def addStatusBar(self):
        # statusbar
        self.sbar = self.CreateStatusBar(3, wx.ST_SIZEGRIP)
        self.sbar.SetStatusWidths([-2, -3, -2])
        self.sbar.SetStatusText("Ready", 0)
        self.sbar.SetStatusText("Welcome To Knobjex, in " + isocalendarst, 1)

    def addMenuBar(self, defMenuli):
        # menu aanmaken
        mbar = wx.MenuBar()
        menu = []
        for menuli in defMenuli:
            it = defMenuli.index(menuli)
            menu.append(wx.Menu())
            mbar.Append(menu[it],menuli[0][0])
            for itemli in menuli[1]:
                subit = menuli[1].index(itemli)
                idit = ((it + 1) * 100) + subit
                if itemli[0] == 'AppendSeparator':
                    getattr(menu[it],itemli[0])()
                else:
                    getattr(menu[it],itemli[0])(idit,itemli[1])
                    # event binding
                    self.Bind(wx.EVT_MENU, self.onMenuEvent, id=idit)
        self.SetMenuBar(mbar)


    def enableMenuItems(self, defMenuli, statebo):
        mbar = self.GetMenuBar()
        for menuli in defMenuli:
            it = defMenuli.index(menuli)
            menu = mbar.GetMenu(it)
            for itemli in menuli[1]:
                subit = menuli[1].index(itemli)
                idit = ((it + 1) * 100) + subit
                if itemli[0] == 'AppendSeparator':
                    pass
                else:
##                    print menu.GetLabel(idit)
                    if statebo == True:
                        menu.Enable(idit, True)
                    else:
                        menu.Enable(idit, itemli[2])

    def addToolbars(self, defToolbarli):
        # toolbars - zie wx13bitmaps voor geldige Art bitmaps
        # get module-path and test if is OK (to find the icon-files)

        iconspathst = curModuleSubDir('icons')
        if iconspathst == '':
            mst = 'The icon-folder could not be determined relatively; ' + \
                'now using static paths from defgui...'
            self.sbar.SetStatusText(mst,0)

##        iconspathst = ''
##        basenamest = os.path.basename(str(sys.argv[0]))
##        (shortnamest, extensionst) = os.path.splitext(basenamest)
##        if shortnamest == 'main_startup':
##            modulepathst = os.path.dirname(str(sys.argv[0]))
##            iconspathst = os.path.join(modulepathst, 'icons')
##        else:
##            mst = 'The icon-folder could not be determined relatively; ' + \
##                'now using static paths from defgui...'
##            self.sbar.SetStatusText(mst,0)
        self.tbar = []
        for toolbarli  in defToolbarli:
            it = defToolbarli.index(toolbarli)
            self.tbar.append(wx.ToolBar(self,-1,wx.DefaultPosition,wx.DefaultSize,
                wx.TB_FLAT | wx.TB_NODIVIDER |wx.TB_DOCKABLE ))
            #        wxTB_HORZ_TEXT   wxTB_VERTICAL
            x = toolbarli[0][1]
            y = toolbarli[0][2]
            self.tbar[it].SetToolBitmapSize(wx.Size(x, y))

            for toolli in toolbarli[1]:
                subit = toolbarli[1].index(toolli)
                idit = ((it + 1) * 1000) + subit
                print 'toolbar idit = ' + str(idit)
                if toolli[1] == 'ap':     # via artProvider
                    artprovob = wx.ArtProvider_GetBitmap(getattr(wx,toolli[2]),
                              wx.ART_OTHER,wx.Size( x,y))
                    self.tbar[it].AddLabelTool(idit,toolli[0], artprovob, shortHelp=toolli[0])
                elif toolli[1] == 'file':      # uit een bestand
                    filefoundbo = False
                    fullNamest = os.path.join(iconspathst,toolli[2])
                    if os.path.isfile(fullNamest):
                        filefoundbo = True
                    else:   # get the hard-coded string from gui-def
                        fullNamest = os.path.join(toolbarli[0][3],toolli[2])
                        if os.path.isfile(fullNamest):
                            filefoundbo = True

                    if filefoundbo:
                        bitmaptypeob = getattr(wx,'BITMAP_TYPE_' + toolli[3] )
                        bitmap = wx.Image(fullNamest, bitmaptypeob).ConvertToBitmap()
                        self.tbar[it].AddLabelTool(idit,toolli[0], bitmap, shortHelp=toolli[0])
                    else:
                        mst = 'Could not find toolbar-icon(s)..'
                        self.sbar.SetStatusText(mst,0)

                # event binding - enable when event-handlers are added
                self.Bind(wx.EVT_MENU, self.onToolbarEvent, id = idit)

            self.tbar[it].Realize()

            tbarName = removeSpaces(toolbarli[0][0])
#            self._mgr.AddPane(self.tbar[it], wx.aui.AuiPaneInfo().
#                Name(tbarName).Caption(toolbarli[0][0]).
#                ToolbarPane().Top().Row(0).
#                LeftDockable(True).RightDockable(True))

            # added position to adapt for linux
            self._mgr.AddPane(self.tbar[it], wx.aui.AuiPaneInfo().
                Name(tbarName).Caption(toolbarli[0][0]).
                ToolbarPane().Top().Row(0).Position(it).
                LeftDockable(True).RightDockable(True))

            self._mgr.GetPane(tbarName).Show()

    def enableToolbarItems(self, defToolbarli, statebo):
        '''
        ADAP FUT
        -make failsafe for absence of toolbar or icons
        '''
        for toolbarli  in defToolbarli:
            it = defToolbarli.index(toolbarli)

            for toolli in toolbarli[1]:
                subit = toolbarli[1].index(toolli)
                idit = ((it + 1) * 1000) + subit
                print 'toolbar idit = ' + str(idit)
##                self.tbar[it].EnableTool(idit, False)   # test

                if statebo == True:
                    self.tbar[it].EnableTool(idit, True)
                else:
                    self.tbar[it].EnableTool(idit, toolli[4])


    def addDynamicPanes(self):

        # dynamische panes instantieren en toevoegen aan manager
        self.panedi = {}
        for pli  in defPaneli:
            pl = pli[0][2]

            paneName = pli[0][1]
            print '==============================='
            print paneName

            it = defPaneli.index(pli)
            # panes instantieren

            self.panedi[pli[0][1]] = getattr(sys.modules[pli[0][0]],
                str(pli[0][1]))(self, it, controlsDefDict = pli[1])

##            jotools.prDict(pl)
            self._mgr.AddPane(self.panedi[pli[0][1]], wx.aui.AuiPaneInfo().
                Name(paneName).Caption(pl['caption']).CaptionVisible(pl['capvis']).
                Direction(pl['direct']).Layer(pl['layer']).
                Row(pl['row']).Position(pl['posit']).BestSize(pl['bestsize']).
                MinSize(pl['minsize']).PinButton(pl['pinbut']).
                MaximizeButton(pl['maxbut']).CloseButton(pl['clobut']))

            if pl['center']==True:
                self._mgr.GetPane(paneName).CenterPane()

            self._mgr.GetPane(paneName).Show()


    def addSpecificPanes(self):     # specific panes
        # statische panes
        self.liscLeft = leftLiscPanel(self,-1)
        self.liscRight = rightLiscPanel(self,-1)
        self.treePane = treecPanel(self, -1)
        self.mainLisc = mainLiscPanel(self,-1)
        self.paramsLisc = paramsLiscPanel(self,-1)

        self._mgr.AddPane(self.liscLeft, wx.aui.AuiPaneInfo().
                    Name("liscleft").Caption('Objects left').
                    Direction(5).Layer(0).Row(0).Position(0).
                    BestSize((1000,1000)).MinSize((100,60)).
                    MinimizeButton(True).PinButton(True).CloseButton(True).
                    MaximizeButton(True).Dockable(True))

        self._mgr.AddPane(self.liscRight, wx.aui.AuiPaneInfo().
                    Name("liscright").Caption('Objects right').
                    Direction(5).Layer(0).Row(1).Position(0).
                    BestSize((1000,1000)).MinSize((100,60)).
                    MinimizeButton(True).PinButton(True).CloseButton(True).
                    MaximizeButton(True).Dockable(True))

        self._mgr.AddPane(self.treePane, wx.aui.AuiPaneInfo().
                    Name("treepane").Caption('Tree view').
                    Direction(2).Layer(2).Row(0).Position(0).
                    BestSize((800,500)).MinSize((50,60)).
                    MinimizeButton(True).PinButton(True).CloseButton(True).
                    MaximizeButton(True).Dockable(True))

        self._mgr.AddPane(self.mainLisc, wx.aui.AuiPaneInfo().
                    Name("mainlisc").Caption('Relations-query').
                    Direction(5).Layer(0).Row(0).Position(0).
                    BestSize((800,1000)).MinSize((100,60)).
                    MinimizeButton(True).PinButton(True).CloseButton(True).
                    MaximizeButton(True).Dockable(True))

        self._mgr.AddPane(self.paramsLisc, wx.aui.AuiPaneInfo().
                    Name("paramslisc").Caption('Options').
                    Direction(5).Layer(0).Row(0).Position(0).
                    BestSize((800,1000)).MinSize((100,60)).
                    MinimizeButton(True).PinButton(True).CloseButton(True).
                    MaximizeButton(True).Dockable(True))

    def showPerspective(self, viewsetst=''):

        '''
        UNIT INFO:
        Show a specific set of panes, and hide the others.
        In the interface this will be called a 'Panel-configs'
        ADAP HIS
        -Create defgui-def
        -load the Panel-configs

        ADAP NO
        '''
        # pre-hide everything
        all_panes = self._mgr.GetAllPanes()
        for it in xrange(len(all_panes)):
            if not all_panes[it].IsToolbar():
                all_panes[it].Hide()

        # show the base panes, that should be allways visible
        for panest in defgui.defBasePerspectiveli:
            self._mgr.GetPane(panest).Show()

        # show the special panes, specially feur you
        for panest in defgui.defPerspectivedi[viewsetst][1]:
            self._mgr.GetPane(panest).Show()

        # update the manager
        self._mgr.Update()

##        self._mgr.GetPane("mainlisc").Hide()
##        self._mgr.GetPane("liConPanel").Hide()

##        self._mgr.GetPane("liscleft").Hide()
##        self._mgr.GetPane("liscright").Hide()
##        self._mgr.GetPane("treepane").Hide()
##        self._mgr.GetPane("navPanel").Hide()


    def onMenuEvent(self, event):
        '''
        UNIT INFO:
        first menu: 100, 101, 102
        sec menu: 200, 201, 202
        etc.
        Share events with the toolbar

        ADAP NO

        '''
        # printBarItems geeft items
##        printBarItems('m')

        idit = event.GetId()
        if idit == 100 :    # menu: file
            self.doCommonAction('NewDb')
        if idit == 101:
            self.doCommonAction('OpenDb')
        if idit == 102:            
            self.doCommonAction('RecentDb')           
        if idit == 103:
            self.doCommonAction('CloseDb')
        if idit == 105:
            self.doCommonAction('DB-info')


        elif idit == 200:   # menu edit
            pass
        elif idit == 201:
            pass

        elif idit == 300:   # menu view
            self.viewPanel('modPanel')

        elif idit == 301:
            self.viewPanel('longTextPanel')

        elif idit == 400:   # menu tools
            self.doCommonAction('EchangeDataAndText')

        elif idit == 401:
            # show modal a window
            dlg = importDialog(None, -1, title = "Import data from file")
##                size=(500, 300))
    ##                         #style=wx.CAPTION | wx.SYSTEM_MENU | wx.THICK_FRAME,
    ##                         style=wx.DEFAULT_DIALOG_STYLE) # & ~wx.CLOSE_BOX,

            dlg.CenterOnScreen()
            # this does not return until the dialog is closed.
            val = dlg.ShowModal()
            dlg.Destroy()
        elif idit == 402:
            # show modal a window
            dlg = exportDialog(self, -1, title = "Export query to text-file")
##                size=(500, 300))
    ##                         #style=wx.CAPTION | wx.SYSTEM_MENU | wx.THICK_FRAME,
    ##                         style=wx.DEFAULT_DIALOG_STYLE) # & ~wx.CLOSE_BOX,

            dlg.CenterOnScreen()
            # this does not return until the dialog is closed.
            val = dlg.ShowModal()
            dlg.Destroy()

        elif idit == 403:
            print 'i am a separator-dummy (and yet i am happy)'
        elif idit == 404:
            self.doCommonAction('LoadOptionsView_db')
        elif idit == 405:
            self.doCommonAction('LoadOptionsView_sys')
        elif idit == 406:
            mst = 'You are about to backup the program-settings to the ' \
                   + 'current database. Proceed?\n\n  ' \
                   + '(the settings-db and the data-db are in fact ' \
                   + 'identical but only used differently).'
            if messageDialog(self, mst, 'Backup settings') == wx.ID_OK:
                wx.SetCursor(wx.HOURGLASS_CURSOR)
                pumpupdabase.pumpAllTables(['PARAMS'],
                        'sqlite3', db_species.settingsdbst,
                        'sqlite3', db_species.curDatabase , 
                        True)
                wx.SetCursor(wx.STANDARD_CURSOR)
                showMessage(self, 'Backup of program-settings complete.',
                    'Ready')

        elif idit == 407:
            mst = 'You are about to restore the program-settings from the ' \
                   + 'current database. Proceed?\n\n  ' \
                   + '(the settings-db and the data-db are in fact ' \
                   + 'identical but only used differently).'
            if messageDialog(self, mst, 'Restore settings') == wx.ID_OK:
                wx.SetCursor(wx.HOURGLASS_CURSOR)
                pumpupdabase.pumpAllTables(['PARAMS'],
                        'sqlite3', db_species.curDatabase,
                        'sqlite3', db_species.settingsdbst , 
                        True)
                wx.SetCursor(wx.STANDARD_CURSOR)
                showMessage(self, 'Restoration of program-settings complete.',
                    'Ready')
                

        elif idit == 500:   # menu windows-sets
            self.doCommonAction('LoadNavigatorView')
        elif idit == 501:
            self.doCommonAction('LoadTaskView')
        elif idit == 502:
            self.doCommonAction('LoadFilterView')
        elif idit == 503:
            self.doCommonAction('LoadOptionsView_db')
        elif idit == 504:
            self.doCommonAction('LoadOptionsView_sys')

        elif idit == 506:
            print '506 - save'
            self.doCustomView('save',1)
        elif idit == 507:
            self.doCustomView('save',2)
        elif idit == 508:
            self.doCustomView('save',3)
        elif idit == 509:
            self.doCustomView('save',4)

        elif idit == 510:
            print '507 - load'
            self.doCustomView('load',1)
        elif idit == 511:
            self.doCustomView('load',2)
        elif idit == 512:
            self.doCustomView('load',3)
        elif idit == 513:
            self.doCustomView('load',4)


        elif idit == 600:   # menu help
            # open help-file
            wx.SetCursor(wx.HOURGLASS_CURSOR)
            helpdirst = curModuleSubDir('help_info')
            filepathst = os.path.join(helpdirst,'Knobjex_handbook.pdf')
            if os.path.isfile(filepathst):
                os_species.runFileAssociatedApp(filepathst)
            else:
                showMessage(self, 'No valid help-file could be found.',
                    'No help-file')

            wx.SetCursor(wx.STANDARD_CURSOR)
        elif idit == 601:   # check updates
            wx.SetCursor(wx.HOURGLASS_CURSOR)
            filepathst = 'http://code.google.com/p/knobjex/downloads/list'
            os_species.runFileAssociatedApp(filepathst)
            wx.SetCursor(wx.STANDARD_CURSOR)

        elif idit == 602:   # about
            # see places.py to test for path-locations etc.
            infost = 'Knobjex code-version ' + str(codeversionfl)  + '\n' \
                    'Minimal database-version ' + str(minimaldatabaseversionfl)  + '\n\n' \
                    'Knobjex; Manage your knowledge and information flexibly. \n' \
                    'Slowly but surely I will develop the app (and add documentation).  \n' \
                    'Feature-ideas or bugs can be sent to the below address. \n' \
                    'Also if someone wants to contribute code \n' \
                    'he or she is welcome and can take part in the project! \n\n' \
                    'Email to: googelaar@gmail.com \n' \
                    'Website: http://code.google.com/p/knobjex \n' \
                    'Created by Joris Bollen 2012, Netherlands. '

            showMessage(self, infost,'About..')
            print 'globalmodulepathst=' + globalmodulepathst
        elif idit == 601:
            pass


    def onToolbarEvent(self, event):
        '''
        UNIT INFO
        -shares events with the menus, here the thousands-range
        has been chosen.
        '''

        # printBarItems geeft items
##        printBarItems('t')

        idit = event.GetId()

        if idit == 1000 :
            print 'item 1000'
            self.doCommonAction('NewDb')
        if idit == 1001 :
            self.doCommonAction('OpenDb')
        if idit == 1002 :
            print 'toolbar recentdb'
            self.doCommonAction('RecentDb')           
        if idit == 1003 :
            self.doCommonAction('CloseDb')
        if idit == 1004 :
            self.doCommonAction('DB-info')

        if idit == 2000 :
            print 'item 2000'
            self.doCommonAction('LoadNavigatorView')
        elif idit == 2001:
            print 'item 2001'
            self.doCommonAction('LoadTaskView')
        elif idit == 2002:
            print 'item 2002'
            self.doCommonAction('LoadFilterView')
        elif idit == 2003:
            print 'item 2003'
            self.doCommonAction('LoadOptionsView_sys')

        elif idit == 2004:
            print 'item 2004'
            self.doCommonAction('LoadOptionsView_db')
        elif idit == 2005:
            self.doCommonAction('EchangeDataAndText')

        elif idit == 3000:
            self.doCustomView('load',1)
        elif idit == 3001:
            self.doCustomView('load',2)
        elif idit == 3002:
            self.doCustomView('load',3)
        elif idit == 3003:
            self.doCustomView('load',4)


    def doCommonAction(self, actionst):
        '''
        UNIT INFO
        Perform events that appear both in the menu and for the toolbars
        '''

        if actionst == 'LoadNavigatorView':
            self.showPerspective('navigator')

        elif actionst == 'LoadTaskView':
            self.showPerspective('querywithmod')
            self.panedi['liConPanel'].ctrldi['lstQuery'].SetSelection(0)
            self.panedi['liConPanel'].setTasks()
            self.panedi['liConPanel'].enableControlSets([['tree-filter' ,False],
                                            ['flat-filter' ,True],
                                            ['change-set' ,False]])
##            self.panedi['liConPanel'].ctrldi['cboField1'].Value = 'Source'
##            self.panedi['liConPanel'].ctrldi['cboOperator1'].Value = 'subs'


            messagest =isocalendarst
            self.sbar.SetStatusText(messagest, 1)

        elif actionst == 'LoadFilterView':
            objecst = self.panedi['navPanel'].ctrldi['cboObject'].Value
            self.showPerspective('querynomod')
            self.panedi['liConPanel'].ctrldi['lstQuery'].SetSelection(1)
            self.panedi['liConPanel'].enableControlSets([['tree-filter' ,True],
                                            ['flat-filter' ,False],
                                            ['change-set' ,True]])

            self.panedi['liConPanel'].setTreeFilter()
            self.panedi['liConPanel'].ctrldi['cboTrRoot'].Value = objecst

        elif actionst == 'LoadOptionsView_db':
            self.showPerspective('options')
            self.paramsLisc.loadDbData('db-level')

        elif actionst == 'LoadOptionsView_sys':
            self.showPerspective('options')
            self.paramsLisc.loadDbData('sys-level')


        elif actionst == 'LoadNullView':
            self.showPerspective('nullview')

        elif actionst == 'EchangeDataAndText':
            dlg = thruportDialog(None, -1, "Thruport data between db and text-files")
    ##                size=(500, 300))
    ##                         #style=wx.CAPTION | wx.SYSTEM_MENU | wx.THICK_FRAME,
    ##                         style=wx.DEFAULT_DIALOG_STYLE) # & ~wx.CLOSE_BOX,

            dlg.CenterOnScreen()
            # this does not return until the dialog is closed.
            val = dlg.ShowModal()
            dlg.Destroy()

        elif actionst == 'NewDb':

            questionst = 'You are about to close the current database, copy ' \
                        + 'a new one from the template-db and load that new ' \
                        + 'database.\n\n Do you want to go on?'
            if messageDialog(self, questionst, 'New database') == wx.ID_OK:
                datadirst = curModuleSubDir('database')
                templatefilepathst =  os.path.join(datadirst,'template.db')
                print datadirst
                print templatefilepathst
                if os.path.isfile(templatefilepathst):
                    newdatabasest = jotools.backupFile(templatefilepathst,
                                                        'knobjex_sqlite')
                    self.loadDatabase(newdatabasest)
                    mst = 'New database created and loaded.'
                else:
                    mst = 'Could not create or load database.'
                showMessage(self, mst, 'Result')

        elif actionst == 'OpenDb':
            pathst = self.doDatabase('choose')
            print pathst
            if pathst <> '':
                self.saveDbToHistory(pathst)
                self.loadDatabase(pathst)

        elif actionst == 'RecentDb':
            # show modal a window
            dlg = recentDbDialog(self, -1, title = "Open recent database")
            dlg.CenterOnScreen()
            # this does not return until the dialog is closed.
            val = dlg.ShowModal()
            dlg.Destroy()
            
        elif actionst == 'CloseDb':
            self.enableMenuItems(defgui.defMenuli, False)
            self.enableToolbarItems(defgui.defToolbarli, False)
            self.doCommonAction('LoadNullView')
        elif actionst == 'DB-info':
            appendst = ''
            if db_species.db_typest:
                appendst = \
                    'DB-version = ' + str(knob_logic.readOption('database_implementation')) + '\n' \
                    'Delivered with code-version = ' + str(knob_logic.readOption('delivered_with_program')) + '\n' \
                    'Relation-count = ' + str(pardb.rowCountFromParams('', 'Relations'))

            messagest = 'Type = ' + db_species.db_typest + '.\n\n'  \
                        'Name = ' + db_species.curDatabase + '.\n\n' \
                        'Below stand the DB-versions. Code-versions are at menu:\n' \
                        'help / about. \n\n' + \
                        appendst
            showMessage(self, messagest, 'Database-info')

        elif actionst == 'ShowExportDialog':

            # show modal a window
            dlg = exportDialog(self, -1, title = "Export query to text-file")
##                size=(500, 300))
    ##                         #style=wx.CAPTION | wx.SYSTEM_MENU | wx.THICK_FRAME,
    ##                         style=wx.DEFAULT_DIALOG_STYLE) # & ~wx.CLOSE_BOX,

            dlg.CenterOnScreen()
            # this does not return until the dialog is closed.
            val = dlg.ShowModal()
            dlg.Destroy()
                

    def doCustomView(self, saveorloadst, numberit):
        # save or load the current windows-config under the relevant number
        viewnamest = 'custom_view_' + str(numberit)
        if saveorloadst == 'save':
            configst = self._mgr.SavePerspective()
            knob_logic.writeOption(viewnamest, 'sys', configst)
        elif saveorloadst == 'load':
            configst = knob_logic.readOption(viewnamest, 'sys')
            if configst  <> None:
                self._mgr.LoadPerspective(configst)


    def loadDatabase(self, optionalpathst = ''):
        # set database and proper gui
        db_statust = self.doDatabase('set', optionalpathst)
        if  db_statust == 'valid_database':
            self.loadAllDbData()
            self.enableMenuItems(defgui.defMenuli, True)
            self.enableToolbarItems(defgui.defToolbarli, True)
            self.doCommonAction('LoadTaskView')
            filenamest = os.path.basename(db_species.curDatabase)
            mst = filenamest
            self.sbar.SetStatusText(mst,2)

        elif db_statust == 'outdated_database':
            # start minimal gui
            self.enableMenuItems(defgui.defMenuli, False)
            self.enableToolbarItems(defgui.defToolbarli, False)
            self.doCommonAction('LoadNullView')
            self.sbar.SetStatusText('No valid db',2)
            showMessage(self,  'Database was recognized but from older version; ' +
                        'please upgrade it with the import-tool. \n\n' +
                        'This tool will now be started, with prepared source-' +
                        'and target-paths. Just follow the procedure. \n\n After import' +
                        'you can rename the upgraded database to your liking' +
                        ' with your file manager...',
                        'Database outdated')
            # prepare import-tool by prepopulating
            # targetdb - copy of template.db
            copysourcedbpathst = os.path.join(curModuleSubDir('database'),'template.db')
            targetfrontst = os.path.splitext(os.path.basename(optionalpathst))[0]
            targetappendst = '_upgrade_to_' + str(codeversionfl)
            targetdbpathst = jotools.copyFile(copysourcedbpathst, targetfrontst, targetappendst, True)
              # show modal a window
            dlg = importDialog(None, -1, title = "Import data from file",
                                sourcepathst = optionalpathst,
                                targetpathst = targetdbpathst,
                                wipetargetbo = True)
            dlg.CenterOnScreen()
            val = dlg.ShowModal()
            dlg.Destroy()

        elif db_statust == 'invalid_file':
            # start minimal gui
            self.enableMenuItems(defgui.defMenuli, False)
            self.enableToolbarItems(defgui.defToolbarli, False)
            self.doCommonAction('LoadNullView')
            self.sbar.SetStatusText('No valid db',2)
            showMessage(self, 'Could not load database; path or file not valid',
                        'DB load failed')
##        self.sbar.SetStatusText('Welcome to Knobjex',0)

    def loadAllDbData(self):
        self.panedi['navPanel'].loadData()
        self.panedi['modPanel'].loadDbData(False)
        self.panedi['liConPanel'].loadDbData()

        self.liscLeft.loadDbData()
        self.liscRight.loadDbData()
        self.mainLisc.loadDbData()
##        self.paramsLisc.loadDbData()

    def doDatabase(self, actionst, optionalpathst=''):
        '''
        ADAP HIS
        - add option in system-settings-database for default-database
            -copy to development-db which will be cloned from
        '''

        # set the path to the db
        if actionst == 'set':
            if optionalpathst <> '':
                db_species.db_typest = 'sqlite3'
                db_species.curDatabase = optionalpathst
            else:
                usemanualconfigbo = False
                if not usemanualconfigbo:

                    # try system-settings-database for default-database
                    optionalpathst = knob_logic.readOption('startup_db', 'sys')

                    if optionalpathst not in ['', None, 'None']:
                        db_species.db_typest = 'sqlite3'
                        db_species.curDatabase = optionalpathst

                    else:
                        # else try of-factory database
                        if globalmodulepathst <> '':
                            db_species.db_typest = 'sqlite3'
                            databasedirst = curModuleSubDir('database')
                            optionalpathst = os.path.join(databasedirst, 'knobjex_sqlite.db')
                            db_species.curDatabase = optionalpathst
                        else:
                            mst = 'The database-folder could not be determined ' + \
                                'relatively. Select it yourself'
                            self.sbar.SetStatusText(mst,0)
                else:
                    # odbc-link to ms access
##                    db_species.db_typest = 'ms access 2000'
##                    db_species.curDatabase = 'KnobjexProductie'

                    # native link to sqlite
                    db_species.db_typest = 'sqlite3'
##                    db_species.curDatabase = 'M:\\EigThuis\\Bestanden\\Leuk\\Hobbies\\Programmeren\\Python\\MijnCode\\PyKnow\\database\\testdeze.db'
                    db_species.curDatabase = 'M:\\EigThuis\\Bestanden\\Planning en Beheer\\Processen en kennis\\kb_sqlite_eigen\\eigen_knobjex.db'
##                    db_species.curDatabase = 'M:\EigThuis\Bestanden\Leuk\Hobbies\Programmeren\Python\MijnCode\PyKnow\database\knobjex_sqlite.db'
                    optionalpathst = db_species.curDatabase

            db_statust = 'invalid_file'     # pre-set
            if db_species.db_typest == 'sqlite3':
                if db_species.testConnectSqlite(optionalpathst):
                    dbversionfl = float(pumpupdabase.getInfoFromDatabase(optionalpathst, True))
                    dbdiffl = dbversionfl - minimaldatabaseversionfl
                    
                    if dbdiffl >= 0:
                        db_statust = 'valid_database'
                        if dbdiffl > 0:
                            mst = 'Database newer than program; update program..'
                            self.sbar.SetBackgroundColour(wx.LIGHT_GREY)
                            self.sbar.SetStatusText(mst,0)

                    else:
                        db_statust = 'outdated_database'
            elif db_species.db_typest == 'ms access 2000':
                db_statust = 'valid_database'
            return db_statust

        elif actionst == 'choose':
            dlg = wx.FileDialog(
                self, message="Choose out your database (*.db*)",
                defaultDir=os.getcwd(),
                defaultFile="",
                wildcard="db files (*.db*)|*.db*|all files (*.*)|*.*",
                style=wx.OPEN | wx.CHANGE_DIR | wx.FD_FILE_MUST_EXIST
                )
            pathst = ''
            if dlg.ShowModal() == wx.ID_OK:
                pathst = dlg.GetPath()
                print pathst
            dlg.Destroy()
            return pathst
    
    def saveDbToHistory(self,  pathst=''):
        # ophalen string
        multipathst = knob_logic.readOption('previous_db_paths', 'sys')
        # verlijsten
        multipathli = multipathst.split(';;')
        # invoegen pad
        newmultipathli = jotools.updateHistoryList(multipathli, pathst, 6)
        # verstringen
        newmultipathst = ';;'.join(newmultipathli)
        # wegschrijven
        knob_logic.writeOption('previous_db_paths', 'sys',  newmultipathst)



    def viewPanel(self, panelst):
        self._mgr.GetPane(panelst).Show()
        self._mgr.Update()


    # wat wazige functies die blijkbaar nodig zijn
    def OnEraseBackground(self, event):
        event.Skip()

    def OnSize(self, event):
        event.Skip()

    def OnClose(self, event):
        self._mgr.UnInit()
        del self._mgr
        self.Destroy()

    def createPanelCtrl(self):
        return wx.Panel(self,-1, wx.Point(0, 0), wx.Size(150, 90),
                           wx.NO_BORDER)


    def CreateTextCtrl(self):
        text = ("This is text box %d")%(self.n + 1)

        return wx.TextCtrl(self,-1, text, wx.Point(0, 0), wx.Size(150, 90),
                           wx.NO_BORDER | wx.TE_MULTILINE)


##class spePanel(getattr(sys.modules[defImports[0]],'genPanel1')):
##    def __init__(self, parent, ID, pos = wx.DefaultPosition,
##            size = wx.DefaultSize, controlsDefDict = None ):
##        getattr(sys.modules[defImports[0]],'genPanel1').__init__(
##            self, parent,ID, pos, size, controlsDefDict)


class navPanel(genFrames.genPanel1):
    '''
    ADAP HIS
    - Query objects based on some criteria.
    - sync cboObject with other cbo's
    - navigational buttons
    -navigate on basis of click  and doubleclick
    -redesign interface:
        -re-use the nav-buttons and associated code
            -button to reread the current object-query
        -later tree-nav
            -tree-root
            -depth
    -add a single-click-mode to navigate
    -2 buttons above single-nav
        - reload current selection
        - sample object
    - favorite-selection must trigger treeload
    -make history immediate
    -lauching websites is slow; bug in python;
        -workaround: open avant
        -wait for 2.6 to use firefox again
    - persistentize history via database vrs_1.1
    - open file, none-url vrs_1.1

    ADAP NO

    ADAP FUT:
    Later:
    - expand cboObjects on entering; try first .popupmenu vrs_1.1
        -else upgrade to comboctrl vrs_1.2
        -or create a dialig with a listcontrol
    '''

    def __init__(self, parent, ID, pos = wx.DefaultPosition,
            size = wx.DefaultSize, controlsDefDict = None ):
        genFrames.genPanel1.__init__(self, parent,ID, pos,
            size, controlsDefDict)
        self.parent = parent
##        self.loadData()

    def loadData(self):
        self.loadModuleData()
        self.loadDbData()

    def loadModuleData(self):
        numli = ['1','2','3','4','5','6','7']
        self.ctrldi['cboTrDepth'].AppendItems(numli)
##        colBase = wx.ColourDatabase()
##        colOne = colBase.Find('YELLOW GREEN')
        colCustom = wx.Color(240,230,180)
        self.ctrldi['cboObject'].SetBackgroundColour(colCustom)

    def loadDbData(self):
        self.ctrldi['cboTrDepth'].Value = str(knob_logic.readOption('treeview_depth'))
        self.ctrldi['chkHide'].Value = knob_logic.readOption('hide_completed')
        self.ctrldi['chkTrLoad'].Value = knob_logic.readOption('treeview_coload')
##        fillComboData(self.ctrldi['cboSource'],'FDQ_SOURCES_GROUPED',['Source'])
##        fillComboData(self.ctrldi['cboSubject'],'FDQ_SUBJECTS_GROUPED',['Subject'])
        fillComboData(self.ctrldi['cboFavo'],'FDQ_FAVORITES',['Object2'])
        fillComboData(self.ctrldi['cboHist'],'FDQ_HISTORY_QUERY',['Object'])
##        fillComboData(self.ctrldi['cboTrRoot'],'Object1Grouped',['Object'])
##        self.enableControlList(['chkUseFilter'],False)


    def onAnyEvent(self, evt):
        '''
        ADAP HIS
        -butSampleFilter
            -copy the filtervalues to globelnavcritdi and to the label
        - make it foolproof
      
        ADAP NO
        '''
    
        t = evt.GetEventType()
        c = evt.GetId()

        try:
            if self.evtTypeIs(t,'BUTTON'):
                if self.ctrlNameIs(c,'butSampleFilter'):
                    globala.navcritdi = self.parent.panedi['liConPanel'].setFlatCriteria()
                    self.ctrldi['labFilter'].SetLabel(str(globala.navcritdi))
                elif self.ctrlNameIs(c,'butClearFilter'):
                    globala.navcritdi = {}
                    self.ctrldi['labFilter'].SetLabel('---')
                    
                elif self.ctrlNameIs(c,'butLaunch'):
                    wx.SetCursor(wx.HOURGLASS_CURSOR)
                    filepathst = self.ctrldi['cboObject'].Value
                    os_species.runFileAssociatedApp(filepathst)
    ##                jotools.openUrl(filepathst)
                    wx.SetCursor(wx.STANDARD_CURSOR)
                elif self.ctrlNameIs(c,'butWeb'):
                    wx.SetCursor(wx.HOURGLASS_CURSOR)
                    # get prepend-clause
                    webclausest = knob_logic.readOption('web_search_clause', 'sys')                    
                    # cochain with object-value
                    filepathst = webclausest + self.ctrldi['cboObject'].Value
                    # launch file-associated app
                    os_species.runFileAssociatedApp(filepathst)
    ##                jotools.openUrl(filepathst)
                    wx.SetCursor(wx.STANDARD_CURSOR)
                 
                elif self.ctrlNameIs(c,'butBack'):
                    his = self.ctrldi['cboHist']
                    oldSelit = his.GetSelection()
                    his.SetSelection(oldSelit + 1)
                    self.readObjects(his.Value, 'cboHist')
                elif self.ctrlNameIs(c,'butFor'):
                    his = self.ctrldi['cboHist']
                    oldSelit = his.GetSelection()
                    his.SetSelection(oldSelit - 1)
                    self.readObjects(his.Value, 'cboHist')
                elif self.ctrlNameIs(c,'butLoad'):
                    self.readCurrentObject()
                elif self.ctrlNameIs(c,'butTrRoot'):
                    # reload treeroot from combo
                    self.loadTreeRoot()
                elif self.ctrlNameIs(c,'butTrObject'):
                    # copy cboObject to cboTreeroot and reload
                    objectst = self.ctrldi['cboObject'].Value
                    if objectst <> '':
                        self.ctrldi['cboTrRoot'].Value = objectst
                        self.loadTreeRoot()
                elif self.ctrlNameIs(c,'butTrLeft'):
                    # copy cboObject to cboTreeroot and reload
                    objectst = self.ctrldi['cboObject'].Value
                    if objectst <> '':
                        self.ctrldi['cboTrRoot'].Value = objectst
                        self.loadTreeRoot('left')
                elif self.ctrlNameIs(c,'butTrSeek'):
                    self.seekTreeObject()
    ##                msg = wx.MessageDialog(None, "Hallo","Bericht",wx.OK)
    ##                msg.ShowModal()
    ##                msg.Destroy()
                elif self.ctrlNameIs(c,'butDepthOne'):
                    self.ctrldi['cboTrDepth'].Value = '1'
                elif self.ctrlNameIs(c,'butDepthTwo'):
                    self.ctrldi['cboTrDepth'].Value = '2'
                elif self.ctrlNameIs(c,'butDepthThree'):
                    self.ctrldi['cboTrDepth'].Value = '3'
                elif self.ctrlNameIs(c,'butDepthFour'):
                    self.ctrldi['cboTrDepth'].Value = '4'
                elif self.ctrlNameIs(c,'butDepthFive'):
                    self.ctrldi['cboTrDepth'].Value = '5'


            elif self.evtTypeIs(t,'TEXT'):
                pass

            elif self.evtTypeIs(t,'TEXT_COPY'):
                pass
            elif self.evtTypeIs(t,'TEXT_ENTER'):
                if self.ctrlNameIs(c,'txtSeek'):
                    txt = self.ctrldi['txtSeek']
                    cbo = self.ctrldi['cboObject']
                    wx.SetCursor(wx.HOURGLASS_CURSOR)
                    cbo.Clear()
                    
                    critobjectdi = {'subs':{'Object': txt.Value}}
                    fillComboData(cbo, 'FDQ_OBJECTS_UNION_GROUPED',['Object'],
                            critobjectdi)
                                
                    wx.SetCursor(wx.STANDARD_CURSOR)
            elif self.evtTypeIs(t,'COMBOBOX'):
                if self.ctrlNameIs(c,'cboObject'):
                    self.readCurrentObject()
                if self.ctrlNameIs(c,'cboHist'):
                    his = self.ctrldi['cboHist']
                    self.readObjects(his.Value, 'cboHist')
                if self.ctrlNameIs(c,'cboFavo'):
                    fav = self.ctrldi['cboFavo']
                    self.readObjects(fav.Value, 'cboFavo')
                    if self.ctrldi['chkTrLoad'].Value:
                        self.ctrldi['cboTrRoot'].Value = fav.Value
                        self.loadTreeRoot()
                if self.ctrlNameIs(c,'cboTrRoot'):
                    loadTreeRoot()
        except:
            messt = 'An unforeseen error occured... \n'  \
                +  '\n' + str(sys.exc_info()[1])
            capst = str(sys.exc_info()[0])
            msg = wx.MessageDialog(self,messt,capst,wx.OK | wx.ICON_ERROR)
            msg.ShowModal()
            msg.Destroy()


    def loadTreeRoot(self, directionst='right'):
        wx.SetCursor(wx.HOURGLASS_CURSOR)
        maxdepthit = int(self.ctrldi['cboTrDepth'].Value)
        mst = 'Loading tree with query-depth ' + str(maxdepthit) \
            + ' - please wait....'
        self.parent.sbar.SetStatusText(mst, 1)
        rootst = self.ctrldi['cboTrRoot'].Value
        if knob_logic.readOption('dynamic_window_caption','sys'):
            self.parent.SetTitle(rootst +
                ' -- Knobjex')
        alttablest = ''
        if directionst == 'left':  # load objects from right to left
            if self.ctrldi['chkUseFilter'].Value:
                self.parent.treePane.loadTree(
                    'FDQ_RELS_TREE_LEFT','baseroot',maxdepthit + 7, rootst,  
                    extracritdi = globala.navcritdi)
            else:
                self.parent.treePane.loadTree(
                    'FDQ_RELS_TREE_LEFT','baseroot',maxdepthit + 7, rootst)
        else:
            if self.ctrldi['chkHide'].Value:
                tablest = 'FDQ_RELS_TREE_RIGHT_OPEN_TASKS'
            else:
                tablest = 'FDQ_RELS_TREE_RIGHT'

            if self.ctrldi['chkUseFilter'].Value:
                self.parent.treePane.loadTree(tablest,'baseroot',maxdepthit,
                    rootst,  extracritdi = globala.navcritdi)
            else:
                self.parent.treePane.loadTree(tablest,'baseroot',maxdepthit,
                    rootst)
##        print 'globala.navcritdi from loadtreeroot = ' + str(globala.navcritdi)
        self.parent.sbar.SetStatusText(isocalendarst, 1)
        wx.SetCursor(wx.STANDARD_CURSOR)


    def seekTreeObject(self):
        '''
        UI:
        Seek the object in the tree and expand the to it
        ADAP NO
        '''

        searchdepthit = knob_logic.readOption('pathway_search_depth')
        treedepthit = searchdepthit + 2
        rootst = self.ctrldi['cboTrRoot'].Value
        objectst = self.ctrldi['cboObject'].Value
        messagest = 'Searching pathway with depth ' + str(searchdepthit) + \
                    '....'
        self.parent.sbar.SetStatusText(messagest, 1)

        pathwayfoundbo = knob_logic.calculatePathway(objectst, rootst,
            'leftobjects', searchdepthit)
        if pathwayfoundbo:
            messagest = 'Pathway found; expanding tree...'
        else:
            messagest = 'Pathway was not found'

        self.parent.sbar.SetStatusText(messagest, 1)

        if pathwayfoundbo:
            if self.ctrldi['chkHide'].Value:
                tablest = 'FDQ_RELS_TREE_RIGHT_PATHWAY_OPEN_TASKS'
            else:
                tablest = 'FDQ_RELS_TREE_RIGHT_PATHWAY'

            self.parent.treePane.loadTree(tablest,'expandpathway',treedepthit,
                    rootst)
            messagest = 'Ready'
            self.parent.sbar.SetStatusText(messagest, 1)


    def readCurrentObject(self):
        obj = self.ctrldi['cboObject']
        self.readObjects(obj.Value, 'cboObject')

    def readObjects(self, objectst, sourcest):
        '''
        ADAP NO
        
        ADAP HIS
        -short-term usage of sql for OR-implementation,
        -mid-term - stored query like RelationsSortedOpenTasks
            -nieuwe queries:
            -FDQ_RELATIONS_SORTED1_OPEN_TASKS
            -FDQ_RELATIONS_SORTED2_OPEN_TASKS
        ADAP FU
        '''
        
        try:
            # set listctrl-dataparameters and conditionally update combos
            if self.ctrldi['chkHide'].Value:
                leftqueryst = 'FDQ_RELATIONS_SORTED1_OPENTASKS'
                rightqueryst = 'FDQ_RELATIONS_SORTED2_OPENTASKS'
            else:
                leftqueryst = 'FDQ_RELATIONS_SORTED1'
                rightqueryst = 'FDQ_RELATIONS_SORTED2'

            if self.ctrldi['chkUseFilter'].Value:
                # set left and right origin
                cleftobjectdi = {'strings':{'Object2':objectst}}
                crightobjectdi = {'strings':{'Object1':objectst}}
                                
                # merge the criteria
                critleftdi = pardb.mergeCritDicts(cleftobjectdi, globala.navcritdi)
                critrightdi = pardb.mergeCritDicts(crightobjectdi,  globala.navcritdi)
            else:
                critleftdi = {'strings':{'Object2':objectst}}
                critrightdi = {'strings':{'Object1':objectst}}


            self.parent.liscLeft.setDataParams('',leftqueryst, None, critleftdi)
            self.parent.liscRight.setDataParams('',rightqueryst, None, critrightdi)

            if sourcest <> 'cboHist':

                knob_logic.updateHistoryTable(objectst)
                his = self.ctrldi['cboHist']
                fillComboData(his,'FDQ_HISTORY_QUERY',['Object'])
                his.SetSelection(0)

            if sourcest <> 'cboObject':
                self.ctrldi['cboObject'].Value = objectst
        except:
            messt = 'An unforeseen error occured... \n'  \
                +  '\n' + str(sys.exc_info()[1])
            capst = str(sys.exc_info()[0])
            msg = wx.MessageDialog(self,messt,capst,wx.OK | wx.ICON_ERROR)
            msg.ShowModal()
            msg.Destroy()



    def goUpDownListCtrl(self, whichPane, directionst):
        # obsolete
        # item-index is zero-based, -1 means no item (?)
        if whichPane == 'left':
            listct = self.parent.liscLeft.lisc
        elif whichPane == 'right':
            listct = self.parent.liscRight.lisc
        if listct.GetItemCount() > 0:
            idit = listct.GetFocusedItem()
            listct.SetFocus()

            if directionst == 'down':
                newidit = idit + 1
            elif directionst == 'up':
                newidit = idit -1
            listct.Focus(newidit)
            listct.Select(newidit)

class modPanel(genFrames.genPanel1):
    '''
    ADAP HIS
    - interface: modify-buttons for undo, save, new isolate, new left,
    new right, new url
    - make datadefinitions - defdatadi; link controls to fields and table
    -read data - triggered  at the lisc-panel
    -write and delete data
    -implement new left, right
        - select object
        - clear the controls that must be renewed, leave the rest based on
        current object.
    -prefill source from sample
    -give feedback in status-bar or otherwise
    -update linked ones
        procedure:
            -changing the right object
                -same-named left objects must co-change
            -changing left
                -same-named rights co-change
    -remake undo
        -reload current relid
    -new right;
        -sample cboObject for object1
    -new left;
        -sample cboObjectfor Object2
    -lock the Relid-control and moddate
    -set moddate in code
    -implement new url from clip vrs.1.0_hi
        -see test wx3
    -entering on the object2-textbox makes a save-operation
        -didnt work; changed tab-order
    -make memo-field multi-lined, zie genFrames
    -extra buttons replacing the labels:
        -copy current record
        -prefill-date for today
    -implement default source
        -if options not empty then the samplelist is set from the options
        -the source is set from the samplelist

    ADAP NO


    ADAP FUT
    -generalize code to genFrame vrs_1.1
    '''

    def __init__(self, parent, ID, pos = wx.DefaultPosition,
            size = wx.DefaultSize, controlsDefDict = None ):
        genFrames.genPanel1.__init__(self, parent,ID, pos,
            size, controlsDefDict)
        self.parent = parent
        self.loadModuleData()
        self.setStyles()
        self.clip = wx.Clipboard()

    def loadData(self):
        self.loadModuleData()
        self.loadDbData()

    def loadModuleData(self):
        self.ctrldi['chkUpdRight'].Value = True
        self.ctrldi['chkUpdLeft'].Value = False
        self.ctrldi['butDelete'].SetForegroundColour(wx.RED)

    def loadDbData(self, allbo = True):
        fillComboData(self.ctrldi['cboSamSource'],'FDQ_SOURCES_GROUPED',['Source'])
        fillComboData(self.ctrldi['cboChange'],'FDQ_CHANGES_GROUPED',['Change'])
        self.ctrldi['cboSamSource'].Value = knob_logic.readOption('default_source')

        if allbo == True:
            fillComboData(self.ctrldi['cboSource'],'FDQ_SOURCES_GROUPED',['Source'])
            fillComboData(self.ctrldi['cboSubject'],'FDQ_SUBJECTS_GROUPED',['Subject'])
            fillComboData(self.ctrldi['cboOb1'],'FDQ_OBJECTS_UNION_GROUPED',['Object'])
            fillComboData(self.ctrldi['cboRel'],'FDQ_RELATIONS_GROUPED',['Relation'])
            fillComboData(self.ctrldi['cboOb2'],'FDQ_OBJECTS_UNION_GROUPED',['Object'])


    def setStyles(self):
        controlli = ['txtRelID','txtModDate','txtCreaDate', \
            'txtCreator','txtImportDate','txtImportedFrom', \
            'txtNumPar','txtNumChi','txtDepthLeft','txtDepthRight', \
            'txtModSource']
##        colBase = wx.ColourDatabase()
##        colOne = colBase.Find('DIM GREY')

        for ctlst in controlli:
            texAt = wx.TextAttr(wx.RED)
            self.ctrldi[ctlst].SetDefaultStyle(texAt)
            self.ctrldi[ctlst].SetEditable(False)
            self.ctrldi[ctlst].SetBackgroundColour(wx.LIGHT_GREY)
##            self.ctrldi[ctlst].SetBackgroundColour(colOne)

    def onAnyEvent(self, evt):
        '''
        ADAP HIS
        -Error-handling
            -To handle errors from DB-restrictions
                -create specific pyodbc.Error-handling
            -reraise unhandled errors when ready
            -finish function showMessage
        ADAP NO
        ADAP FU
        
        '''

        try:
            t = evt.GetEventType()
            c = evt.GetId()

            if self.ctrldi['txtRelID'].Value <> '':
                relidit = int(self.ctrldi['txtRelID'].Value)

            if self.evtTypeIs(t,'BUTTON'):
                if self.ctrlNameIs(c,'butLoadLists'):
                    wx.SetCursor(wx.HOURGLASS_CURSOR)
                    messagest = '(re-)loading pick-lists...please wait'
                    self.parent.sbar.SetStatusText(messagest, 0)
                    self.parent.panedi['navPanel'].readCurrentObject()
                    self.loadDbData()
##                    if self.ctrldi['txtRelID'].Value <> '':
##                        self.readRecord(relidit)
                    messagest = 'Lists loaded'
                    self.parent.sbar.SetStatusText(messagest, 0)
                    wx.SetCursor(wx.STANDARD_CURSOR)
                elif self.ctrlNameIs(c,'butSave'):
                    self.ctrldi['txtModDate'].Value = str(datetime.today())[:19]
                    samplesourcest = str(self.ctrldi['cboSamSource'].Value)
                    currentsourcest = str(self.ctrldi['cboSource'].Value)
                    if not samplesourcest in ['', 'None']:
                        self.ctrldi['cboSource'].Value = samplesourcest
                    self.ctrldi['txtModSource'].Value = self.updateModSource(
                        samplesourcest, str(self.ctrldi['txtModSource'].Value))

                    if self.ctrldi['txtRelID'].Value <> '':     # UPDATE
                        # Update of related objects:
                        # store the new object-values
                        newleftobst = self.ctrldi['cboOb1'].Value
                        newrightobst = self.ctrldi['cboOb2'].Value
                        # read the old object-values from db based on relid
                        oldleftobli = pardb.readFromParams('', 'Relations',['Object1'],
                            {'numbers':{'RelID':relidit}})
                        oldleftobst = str(oldleftobli[0][0])
                        oldrightobli = pardb.readFromParams('', 'Relations',['Object2'],
                            {'numbers':{'RelID':relidit}})
                        oldrightobst = str(oldrightobli[0][0])
                        # show message for confirmation
                            #to be implemented
                        self.writeRecord('update', {'numbers':{'RelID':relidit}})
                        # conditionally update related objects
                        mestailst = 'None'
                        if self.ctrldi['chkUpdRight'].Value == True:
                            pardb.updateFromParams('', 'Relations',
                                {'strings':{'Object1':newrightobst}},
                                {'strings':{'Object1':oldrightobst}})
                            pardb.updateFromParams('', 'Relations',
                                {'strings':{'Object2':newrightobst}},
                                {'strings':{'Object2':oldrightobst}})
                            mestailst = '2'
                        if self.ctrldi['chkUpdLeft'].Value == True:
                            pardb.updateFromParams('', 'Relations',
                                {'strings':{'Object2':newleftobst}},
                                {'strings':{'Object2':oldleftobst}})
                            pardb.updateFromParams('', 'Relations',
                                {'strings':{'Object1':newleftobst}},
                                {'strings':{'Object1':oldleftobst}})

                            if mestailst == 'None':
                                mestailst = '1'
                            else:
                                mestailst = mestailst + ' and 1'
                        messagest = "Record " + str(relidit) \
                            + ' updated. Two-sided links updated from object: ' \
                            + mestailst
                        self.parent.sbar.SetStatusText(messagest, 1)
                    else:                                       # ADDNEW
                        self.ctrldi['txtCreaDate'].Value = str(datetime.today())[:19]
                        defaultcreatorst =  knob_logic.readOption('default_creator')
                        if defaultcreatorst == 'auto':
#                            computerst = str(os.getenv('COMPUTERNAME'))
#                            usernamest = str(os.getenv('USERNAME'))

                            # linux-adap
                            computerst = str(os_species.getObName('computer'))
                            usernamest = str(os_species.getObName('user'))
                            
                            self.ctrldi['txtCreator'].Value = computerst + \
                                ' / ' + usernamest + ' / ' + samplesourcest
                        else:
                            self.ctrldi['txtCreator'].Value = defaultcreatorst \
                                 + ' / ' + samplesourcest

                        newidit = self.writeRecord('addnew')
                        self.readRecord(newidit)
                        messagest = "Record added on: " + str(datetime.today())[:19]
                        self.parent.sbar.SetStatusText(messagest, 1)
                    # reread the lists
                    self.parent.panedi['navPanel'].readCurrentObject()
                    self.rereadLists()

##                    querytypest = self.parent.panedi['liConPanel'].ctrldi['lstQuery'].GetStringSelection()
##                    if querytypest == 'Calendar / task-list':
##                        myparent = self.parent.panedi['liConPanel']
##                        myparent.setTasks(myparent.ctrldi['lstQuerSub'].GetStringSelection())
##
##                    elif querytypest == 'Flat filter only':
##                        self.parent.panedi['liConPanel'].setFlatFilter(querytypest,
##                                    self.parent.panedi['liConPanel'].setFlatCriteria())
##                    # dont requery trees after a single update


                elif self.ctrlNameIs(c,'butNew'):
                    self.clearControls()
                    samplesourcest = str(self.ctrldi['cboSamSource'].Value)
                    if samplesourcest <> '':
                        self.ctrldi['cboSource'].Value = samplesourcest
                    self.ctrldi['cboOb1'].SetFocus()
                    self.parent.sbar.SetStatusText( \
                        "Fill the fields for new record and save it", 0)
                elif self.ctrlNameIs(c,'butNewLe'):
                    self.clearSomeControls('left')
                    self.ctrldi['cboOb2'].Value = \
                        self.parent.panedi['navPanel'].ctrldi['cboObject'].Value
                    samplesourcest = str(self.ctrldi['cboSamSource'].Value)
                    if samplesourcest <> '':
                        self.ctrldi['cboSource'].Value = samplesourcest
                    self.ctrldi['cboRel'].Value = 'x'
                    self.ctrldi['cboOb1'].SetFocus()
                    self.parent.sbar.SetStatusText( \
                        "Fill the fields for new record and save it", 0)
                elif self.ctrlNameIs(c,'butNewRi'):
                    self.clearSomeControls('right')
                    self.ctrldi['cboOb1'].Value = \
                        self.parent.panedi['navPanel'].ctrldi['cboObject'].Value
                    samplesourcest = str(self.ctrldi['cboSamSource'].Value)
                    if samplesourcest <> '':
                        self.ctrldi['cboSource'].Value = samplesourcest
                    self.ctrldi['cboRel'].Value = 'x'
                    self.ctrldi['cboRel'].SetFocus()
                    self.parent.sbar.SetStatusText( \
                        "Fill the fields for new record and save it", 0)
                elif self.ctrlNameIs(c,'butNewClip'):
                    c = self.clip
                    if c.Open():
                        data = wx.TextDataObject()
                        c.GetData(data)
                        clipst = data.GetText()
                        print clipst
                        c.Close()
                    else:
                       print 'Could not open clipboard.'
                    self.clearSomeControls('right')
                    self.ctrldi['cboOb1'].Value = \
                        self.parent.panedi['navPanel'].ctrldi['cboObject'].Value
                    self.ctrldi['cboOb2'].Value = clipst
                    self.ctrldi['cboRel'].Value = 'file-path'
                    samplesourcest = str(self.ctrldi['cboSamSource'].Value)
                    if samplesourcest <> '':
                        self.ctrldi['cboSource'].Value = samplesourcest
                    self.parent.sbar.SetStatusText( \
                        "Fill the fields for new record and save it", 0)

                elif self.ctrlNameIs(c,'butDelete'):
                    delobject2st = self.ctrldi['cboOb2'].Value[:15]
                    pardb.deleteFromParams('', 'Relations',{'numbers':{'RelID':relidit}})
                    messagest = 'Deleted record: ' + str(relidit) + ' ('  \
                        + delobject2st + '...) on ' + str(datetime.today())[:19]
                    self.parent.sbar.SetStatusText(messagest,1)
                    self.parent.panedi['navPanel'].readCurrentObject()
##                    self.parent.panedi['liConPanel'].setTasks()
                    # reread the lists
                    self.rereadLists()

                elif self.ctrlNameIs(c,'butMsDate'):
                    self.ctrldi['txtMsDate'].Value = datest
                elif self.ctrlNameIs(c,'butPlusSeven'):
                    datec = self.ctrldi['txtMsDate']
                    datec.Value = jotools.dateCountDelta(datec.Value, +7)
                elif self.ctrlNameIs(c,'butMinOne'):
                    datec = self.ctrldi['txtMsDate']
                    datec.Value = jotools.dateCountDelta(datec.Value, -1)
                elif self.ctrlNameIs(c,'butPlusOne'):
                    datec = self.ctrldi['txtMsDate']
                    datec.Value = jotools.dateCountDelta(datec.Value, 1)
                elif self.ctrlNameIs(c,'butMsDateClear'):
                    self.ctrldi['txtMsDate'].Value = ''
                elif self.ctrlNameIs(c,'butChange'):
                    self.ctrldi['cboChange'].Value = 'h'
                elif self.ctrlNameIs(c,'butChangeClear'):
                    self.ctrldi['cboChange'].Value = ''


            elif self.evtTypeIs(t,'TEXT'):
                pass
            elif self.evtTypeIs(t,'TEXT_COPY'):
                pass
            elif self.evtTypeIs(t,'TEXT_ENTER'):
                if self.ctrlNameIs(c,'cboOb2'):
                    # doesnt seem to work for combobox
                    print 'zzzzzzzzzzzzzzzzzzzzzzzz'
            elif self.evtTypeIs(t,'COMBOBOX'):
                if self.ctrlNameIs(c,'cboOb2'):
                    pass
##        except pyodbc.Error:
##            messt = 'A database-error occured; read info carefully \
##            and retry.\n' +  '\n' + str(sys.exc_info()[1])
##            capst = str(sys.exc_info()[0])
##            msg = wx.MessageDialog(self,messt,capst,wx.OK | wx.ICON_WARNING)
##            msg.ShowModal()
##            msg.Destroy()
        except UnicodeEncodeError:
            messt = 'For now knobjex can not store unicode characters. \
            \n' +  '\n' + str(sys.exc_info()[1])
            capst = str(sys.exc_info()[0])
            msg = wx.MessageDialog(self,messt,capst,wx.OK | wx.ICON_WARNING)
            msg.ShowModal()
            msg.Destroy()
        except UnboundLocalError:
            messt = 'You can not count up or down an empty or invalid date. \
            \n' +  '\n' + str(sys.exc_info()[1])
            capst = str(sys.exc_info()[0])
            msg = wx.MessageDialog(self,messt,capst,wx.OK | wx.ICON_WARNING)
            msg.ShowModal()
            msg.Destroy()
        except:
            messt = 'An unforeseen error occured... \n'  \
                +  '\n' + str(sys.exc_info()[1])
            capst = str(sys.exc_info()[0])
            msg = wx.MessageDialog(self,messt,capst,wx.OK | wx.ICON_ERROR)
            msg.ShowModal()
            msg.Destroy()
##            raise


    def clearSomeControls(self, directionst):
        if directionst == 'left':
            clearli = ['txtMsNum', 'txtRemark', 'txtRelID',  \
            'chkSel', 'txtMsDate',  'cboOb1', 'cboRel', 'txtModDate', \
            'txtMsCur', 'txtMsLtext', 'cboChange','txtCreaDate', \
            'txtCreator','txtProject','txtImportDate','txtImportedFrom', \
            'txtNumPar','txtNumChi','txtDepthLeft','txtDepthRight', \
            'txtModSource']
        elif directionst == 'right':
            clearli = ['txtMsNum', 'txtRemark', 'txtRelID',  \
            'chkSel', 'txtMsDate',  'cboOb2', 'cboRel', 'txtModDate', \
            'txtMsCur', 'txtMsLtext', 'cboChange','txtCreaDate', \
            'txtCreator','txtProject','txtImportDate','txtImportedFrom', \
            'txtNumPar','txtNumChi','txtDepthLeft','txtDepthRight', \
            'txtModSource']
        self.clearControls(clearli)

    def clearControls(self,mycontrolli=[]):
        '''
        ADAP HIS
        - clear controls based on type
        - added custom-list
        - always clear longtextpanel
        '''

        if mycontrolli == []:
            controlli2 = defDatadi['modPanel'][1].values()
            controlli = [a for a,b in controlli2]
        else:
            controlli= mycontrolli

        for ctrlst in controlli:
            ctrl = self.ctrldi[ctrlst]
            ctrltypest = str(type(ctrl))

            if ctrltypest == "<class 'wx._controls.CheckBox'>":
                ctrl.Value = 0
            else:
                ctrl.Value = ''
        
        self.copyLongText('clear')
        

    def writeRecord(self, writetypest, wheredi={}):
        '''
        ADAP HIS
        -write control-data to database; specifiy Addnew or Update
        ADAP NO

        ADAP FU
        '''
        
        self.copyLongText('big2small')  # pre-copy textpanel to textbox

        fieldvaluedi = {}
        setdi = {}
        setstringdi = {}
        setnumdi = {}
        setsubdi = {}
        setnullsli = []
##        fieldtypedi = pardb.getDataTypeDict('', defDatadi['modPanel'][0])
        fieldtypedi = pardb.getDataTypeDict('', 'Relations')
        print fieldtypedi
        ctrlfielddi =defDatadi['modPanel'][1]
        print ctrlfielddi
        for fieldtu in ctrlfielddi.items():
            if not fieldtu[1][1] == 'readonly': # handletype
                fieldnamest = fieldtu[0]
                ctrlnamest = fieldtu[1][0]
                ctrlvalue = self.ctrldi[ctrlnamest].Value
                fieldtypest = fieldtypedi[fieldnamest]
                print fieldnamest
                print ctrlvalue
                if str(type(ctrlvalue)) == "<type 'unicode'>":
                    # convert unicode to string
                    ctrlvalue = ctrlvalue.encode('latin-1', 'replace')
                    ctrlvalue = ctrlvalue.replace("\'","~")
                    ctrlvalue = ctrlvalue.replace('\"','~')

                if db_species.db_typest == 'sqlite3':
                    if fieldtypest == "TEXT" or \
                            fieldtypest == "DATE":
                        if writetypest == 'addnew':
                            if ctrlvalue <> '':
                                fieldvaluedi[fieldnamest] = ctrlvalue
                        elif writetypest == 'update':
                            if ctrlvalue <> '':
                                setstringdi[fieldnamest] = ctrlvalue
                            else:
                                setnullsli.append(fieldnamest)
                    elif fieldtypest == "INTEGER":
                        if writetypest == 'addnew':
                            if ctrlvalue <> '':
                                fieldvaluedi[fieldnamest] = int(ctrlvalue)
                        elif writetypest == 'update':
                            if ctrlvalue <> '':
                                setnumdi[fieldnamest] = int(ctrlvalue)
                            else:
                                setnullsli.append(fieldnamest)
                    elif fieldtypest == "REAL":
                        if writetypest == 'addnew':
                            if ctrlvalue <> '':
                                fieldvaluedi[fieldnamest] = float(ctrlvalue)
                        elif writetypest == 'update':
                            if ctrlvalue <> '':
                                setnumdi[fieldnamest] = float(ctrlvalue)
                            else:
                                setnullsli.append(fieldnamest)

                elif db_species.db_typest == 'ms access 2000':
                    if fieldtypest == "<type 'unicode'>" or \
                            fieldtypest == "<type 'datetime.datetime'>":
                        if writetypest == 'addnew':
                            if ctrlvalue <> '':
                                fieldvaluedi[fieldnamest] = ctrlvalue
                        elif writetypest == 'update':
                            if ctrlvalue <> '':
                                setstringdi[fieldnamest] = ctrlvalue
                            else:
                                setnullsli.append(fieldnamest)
                    elif fieldtypest == "<type 'int'>":
                        if writetypest == 'addnew':
                            if ctrlvalue <> '':
                                fieldvaluedi[fieldnamest] = int(ctrlvalue)
                        elif writetypest == 'update':
                            if ctrlvalue <> '':
                                setnumdi[fieldnamest] = int(ctrlvalue)
                            else:
                                setnullsli.append(fieldnamest)
                    elif fieldtypest == "<type 'float'>":
                        if writetypest == 'addnew':
                            if ctrlvalue <> '':
                                fieldvaluedi[fieldnamest] = float(ctrlvalue)
                        elif writetypest == 'update':
                            if ctrlvalue <> '':
                                setnumdi[fieldnamest] = float(ctrlvalue)
                            else:
                                setnullsli.append(fieldnamest)
                    elif fieldtypest == "<type 'bool'>":
                        if writetypest == 'addnew':
                            if ctrlvalue <> '':
                                fieldvaluedi[fieldnamest] = ctrlvalue
                        elif writetypest == 'update':
                            setnumdi[fieldnamest] = int(ctrlvalue)

        print fieldvaluedi

        newidit = -1    # init-value
        if writetypest == 'addnew':
            newidit = pardb.addnewFromParamsWithNewID('', 'Relations', fieldvaluedi)
        elif writetypest == 'update':
            setdi = {'strings':setstringdi,'numbers':setnumdi,'nullslist':setnullsli}
            pardb.updateFromParams('', 'Relations', setdi, wheredi )
        return newidit


    def readRecord(self, relid):
        '''
        ADAP HIS
        -retrieves data-cursor based on list-control-focus and RelID
        -writes data to controls with help of fieldlist, datatypelist
        and defdatadi

        ADAP NO
        ADAP FUT
        -??adapt for datatypes and specific controls, esp. wx.datepickerctrl
        -??create a function: convertType(value, datatype, direction)
        -move function later to genFrame
        '''

        curli = pardb.readFromParams('', 'Relations', None,
                        {'numbers':{'RelID':relid}})
        fieldli = pardb.getFieldList('', 'Relations')
        datatypeli = pardb.getDataTypeList('', 'Relations')
        for row in curli: # only 1 row here
            n = 0
            for val in row:
                if db_species.db_typest == 'ms access 2000':
                    ctrlnamest = defDatadi['modPanel'][1][str(fieldli[n])][0]
                    if str(val) == 'None':
                        valst = ''
                    else:
                        valst = str(val)
                    if str(datatypeli[n]) == "<type 'bool'>":
                        self.ctrldi[ctrlnamest].Value = bool(val)
                    elif str(datatypeli[n]) == "<type 'datetime.datetime'>":
                        self.ctrldi[ctrlnamest].Value = valst
                    else:
                        self.ctrldi[ctrlnamest].Value = valst
                    n = n + 1
                elif db_species.db_typest == 'sqlite3':
                    ctrlnamest = defDatadi['modPanel'][1][str(fieldli[n])][0]
                    if ctrlnamest <> 'NoCtrl':
                        if str(val) == 'None':
                            valst = ''
                        else:
                            valst = str(val)
                        if str(datatypeli[n]) == 'INTEGER':
                            if str(fieldli[n]) == 'Selected':
                                self.ctrldi[ctrlnamest].Value = bool(val)
                            else:
                                self.ctrldi[ctrlnamest].Value = valst
                        else:
                            self.ctrldi[ctrlnamest].Value = valst
                        n = n + 1
        self.copyLongText('small2big')


    def copyLongText(self,  directionst):
        
        bigbox = self.parent.panedi['longTextPanel'].ctrldi['txtLongText']
        smallbox = self.ctrldi['txtMsLtext']
        
        if directionst == 'clear':
            bigbox.Value = ''
        elif directionst == 'small2big':
            bigbox.Value = smallbox.Value
            

        if self.parent._mgr.GetPane('longTextPanel').IsShown():
            self.enableControlList(['txtMsLtext'], False)
            if directionst == 'big2small':
                smallbox.Value = bigbox.Value
        else:
            self.enableControlList(['txtMsLtext'], True)
            

#        if self.parent._mgr.GetPane('longTextPanel').IsShown():
#            print 'welcome txtpane'
#        else:
#            print 'geen txtpane'

    def updateModSource(self, newsourcest, currentmodsourcest):
        # prepend new source to current modsource if it is new
        # 'insert' is procedure appearantly, not a function

        if currentmodsourcest != '':
            curmodsourceli = currentmodsourcest.split("--")
            print curmodsourceli
            if curmodsourceli[0] <> newsourcest:
                print curmodsourceli[0]
                print newsourcest
                newmodsourceli = curmodsourceli
                newmodsourceli.insert(0, newsourcest)
                print newmodsourceli
                newmodsourcest = "--".join(newmodsourceli)
                return newmodsourcest
            else:
                return currentmodsourcest
        else:
            return newsourcest

    def rereadLists(self):
        liconpanel = self.parent.panedi['liConPanel']
        querytypest = liconpanel.ctrldi['lstQuery'].GetStringSelection()
        if querytypest == 'Calendar / task-list':
            liconpanel.setTasks(liconpanel.ctrldi['lstQuerSub'].GetStringSelection())

        elif querytypest == 'Flat filter only':
            liconpanel.setFlatFilter(querytypest,liconpanel.setFlatCriteria())


class liConPanel(genFrames.genPanel1):
    '''
    ADAP HIS
    -list-control-panel overlaps treeview
        -standard-pane (defPaneli)
            -determine a good orientation
                -direction 2, layer 2,r1,p0
    - tree-linked relations-handling (=relations temp) vrs_1.1
        -forefill tree-controls
            -on listbox-selection event
        -fill table Relations temp with tree-recs
            -check msaccess-code
        -show temptable in list
        -delete recs from real table on basis of temp table
        -create question before delete
    -flat filter rels-handling
        v-enable relevant controls
        v-prefill the combos with data-fields
            v-seek field-list in defgui.defdatadi
        v-adapt controls
            v-move up the clear-button
            v-insert a button "get sql"
            v-add operator-combos
            v-rename 'subquery' to 'get recs'
        v-generate criteria
            v-review similar code
            v-check and prepare query in database
        v-retrieve the records
        v-add error-code for wrongly filled fields
        v-nulllist expects list, not dict
        v-generalize double-click and modpanel-function
    -change-operations
        -update
            -moddate-stamp should be of now i.s.o. startup
    -combined tree and flat filter.
        -query combined instead of flat by probing lstQuery
    v-calendar-feature with source, maybe with flat filter
    -source-querying can use 'start with'-type
    (task-forwarding is done by prefixing the new owner in the source-field)
        -compareclause in pardb
    -create an chkbox-option to in-/exclude multi-parent objects
    (to prevent unwanted deletions)
        v-add checkbox
        v-adapt functions readBrancheToTable and readBrancheCycle
        -clean up

    ADAP NO


    ADAP FUT:
    -change-operations
        -update -add combo for fieldtype
    -adaptable criteria not done because of dict-conversion error
    -new criteria like bigger/smaller than, starts with
    -create extra security for update:
        -chkEnableUpdate
    '''

    def __init__(self, parent, ID, pos = wx.DefaultPosition,
            size = wx.DefaultSize, controlsDefDict = None ):
        genFrames.genPanel1.__init__(self, parent,ID, pos,
            size, controlsDefDict)
        self.parent = parent
        self.loadModuleData()

    def loadData(self):
        self.loadModuleData()
        self.loadDbData()


    def loadModuleData(self):
        queryTypesli = ['Calendar / task-list','Tree filter only', \
            'Flat filter only', 'Tree and flat filter']
        self.ctrldi['lstQuery'].InsertItems(queryTypesli,0)
        directionsli = ['rightobjects','leftobjects']
        self.ctrldi['lstDir'].InsertItems(directionsli,0)
        self.ctrldi['lstDir'].SetSelection(0)
        self.subqueriesli = ['FDQ_RELS_TASKS','FDQ_RELS_TASKS_TWOWEEKS', 
                             'FDQ_RELS_TASKS_SOMEDAYS']
        self.ctrldi['lstQuerSub'].InsertItems(self.subqueriesli,0)

        self.ctrldi['chkMultiParent'].Value = True

        operatorli = ['strings','subs','beginwith', 'endwith', 
                      'stringsnot', 'subsnot', 
                      'str_bigger',  'str_smaller', 
                        'numbers', 'num_bigger', 'num_smaller', 
                        'nullslist', 'nullsnot']

        operatorli.append('')
        self.ctrldi['cboOperator1'].AppendItems(operatorli)
        self.ctrldi['cboOperator2'].AppendItems(operatorli)
        self.ctrldi['cboOperator3'].AppendItems(operatorli)

        self.ctrldi['chkManualSql'].Value = False

##        self.enableControlList(['butDel'])
        self.ctrldi['butDel'].Enable(False)

        self.enableControlSets([['tree-filter' ,False],
                                ['flat-filter' ,True],
                                ['change-set' ,False]])



    def loadDbData(self):
        fieldli = pardb.getFieldList('', 'Relations')
        fieldli.append('')
        self.ctrldi['cboField1'].AppendItems(fieldli)
        self.ctrldi['cboField2'].AppendItems(fieldli)
        self.ctrldi['cboField3'].AppendItems(fieldli)
        self.ctrldi['cboFldUpd'].AppendItems(fieldli)


    def onAnyEvent(self, evt):
        '''
        ADAP NO
        '''
        try:
            t = evt.GetEventType()
            c = evt.GetId()

            cset = defgui.defLiconSetsdi

            if self.evtTypeIs(t,'BUTTON'):
                if self.ctrlNameIs(c,'butQuerTree'):
                    self.loadTreeFilter()
                elif self.ctrlNameIs(c,'butDel'):

                    querytypest = self.ctrldi['lstQuery'].GetStringSelection()
                    if messageDialog(self,
                            'Are you sure you want to DELETE the records? \n\n' + \
                            'Delete uses the latest filter-settings which \n' + \
                            'you may not yet have retrieved. \n' + \
                            '(and you might want to backup your database).',
                            'About to delete...')==wx.ID_OK:
                        wx.SetCursor(wx.HOURGLASS_CURSOR)
                        if querytypest == 'Tree filter only':
                            knob_logic.doMatchingRelations('delete')
                            self.loadTreeFilter()
                        elif querytypest == 'Flat filter only':
                            pardb.deleteFromParams('', 'Relations',
                                    self.setFlatCriteria())
                            self.setFlatFilter(querytypest ,self.setFlatCriteria())
                        elif querytypest == 'Tree and flat filter':
                            knob_logic.doMatchingRelations('delete',
                                                    self.setFlatCriteria())
                            self.loadTreeFilter()

                        wx.SetCursor(wx.STANDARD_CURSOR)


                elif self.ctrlNameIs(c,'butGetCrit'):                    
                    self.setFlatCriteria(self.ctrldi['chkManualSql'].Value)
#                    self.ctrldi['cboValue1'].SetFocus() # test
##                    x = self.parent.panedi['liConPanel'].ctrldi['cboValue1'].HasFocus()
#                    x = self.parent.panedi['liConPanel'].ctrldi['cboValue1'].HasCapture()
#                    if x:
#                        print 'ik heb focus'
#                    else: 
#                        print 'got nothing'
#                        print x
                        
                        
                elif self.ctrlNameIs(c,'butQuerFlat'):
                    # one cannot convert a string to a dict (python-bug?)
    ##                if self.ctrldi['chkManualSql'].Value == True:
    ##                    self.setFlatFilter(dict(self.ctrldi['txtCrit'].Value))
    ##                else:

                    querytypest = str(self.ctrldi['lstQuery'].GetStringSelection())
                    self.setFlatFilter(querytypest, self.setFlatCriteria(
                                            self.ctrldi['chkManualSql'].Value))

                elif self.ctrlNameIs(c,'butClear'):
                    self.clearControlList()
                elif self.ctrlNameIs(c,'butUpd'):
                    querytypest = self.parent.panedi['liConPanel']. \
                                ctrldi['lstQuery'].GetStringSelection()
                    if messageDialog(self,
                            'Are you sure you want to update the records? \n\n' + \
                            'Update uses the latest filter-settings which \n' + \
                            'you may not yet have retrieved. \n' + \
                            '(and you might want to backup your database).',
                            'About to update...')==wx.ID_OK:
                        wx.SetCursor(wx.HOURGLASS_CURSOR)
                        self.parent.sbar.SetStatusText('Updating...', 1)
                        fieldst = str(self.ctrldi['cboFldUpd'].Value)
                        valuest = self.ctrldi['txtValUpd'].Value
                        if  len(valuest) == 0:                           
                            updatecritdi = {'strings': {'modDate': str(datetime.today())[:19]}, 
                                                'nullslist':[fieldst]}
                        else:
                            updatecritdi = {'strings': {fieldst:valuest,
                                                'modDate': str(datetime.today())[:19]}}
    ##                    print updatecritdi
                        if querytypest == 'Tree filter only':
                            knob_logic.doMatchingRelations('update',None, updatecritdi)
                            self.loadTreeFilter()
                        elif querytypest == 'Flat filter only':
                            selectcritdi = self.setFlatCriteria()
    ##                        print selectcritdi
                            pardb.updateFromParams('', 'Relations', updatecritdi,
                                                    selectcritdi)
                            self.setFlatFilter(querytypest, self.setFlatCriteria())

                        elif querytypest == 'Tree and flat filter':
                            selectcritdi = self.setFlatCriteria()
                            knob_logic.doMatchingRelations('update',
                                                selectcritdi, updatecritdi)
                            self.loadTreeFilter()
                            self.setFlatFilter(querytypest, self.setFlatCriteria())

                elif self.ctrlNameIs(c,'butExport'):

                    self.parent.doCommonAction('ShowExportDialog')
##                    # show modal a window
##                    dlg = exportDialog(self, -1, title = "Export query to text-file")
##
##                    dlg.CenterOnScreen()
##                    # this does not return until the dialog is closed.
##                    val = dlg.ShowModal()
##                    dlg.Destroy()

                elif self.ctrlNameIs(c,'butMetrics'):
                    querytypest = self.parent.panedi['liConPanel']. \
                                ctrldi['lstQuery'].GetStringSelection()

                    messagest = 'You are about to calculate some metrics. \n\n' + \
                            'Metric-values are updated for the currently filtered set \n' + \
                            'of records, and can be queried like any other field. \n' + \
                            'The values "number of parent- and child-objects" are \n' + \
                            'always  calculated, the left and right depth-values \n' + \
                            'are scanned for the maximal depth (0 skips depth-scan):'

                    dlg = wx.TextEntryDialog(self, messagest, 'Set scan-depth',
                            '10')

                    if dlg.ShowModal() == wx.ID_OK:
                        scandepthit = int(dlg.GetValue())

                        wx.SetCursor(wx.HOURGLASS_CURSOR)
                        self.parent.sbar.SetStatusText('Starting calculation...', 1)

                        #------------------------------------------
                        #------------------------------------------

                        if querytypest == 'Tree filter only':
                            knob_logic.calculateMetricFields('RelationsTemp',
                                                    None, scandepthit)
                            self.loadTreeFilter()

                        elif querytypest == 'Flat filter only':
                            selectcritdi = self.setFlatCriteria()
                            knob_logic.calculateMetricFields('Relations',
                                            selectcritdi, scandepthit)
                            self.setFlatFilter(querytypest, self.setFlatCriteria())

                        elif querytypest == 'Tree and flat filter':
                            selectcritdi = self.setFlatCriteria()
                            knob_logic.calculateMetricFields('RelationsTemp',
                                            selectcritdi, scandepthit)

                            self.loadTreeFilter()
                            self.setFlatFilter(querytypest, self.setFlatCriteria())

                        else:
                            wx.SetCursor(wx.STANDARD_CURSOR)
                            self.parent.sbar.SetStatusText('No metrics for tasks-query', 1)

                    dlg.Destroy()


            elif self.evtTypeIs(t,'TEXT'):
                pass
            elif self.evtTypeIs(t,'TEXT_COPY'):
                pass
            elif self.evtTypeIs(t,'TEXT_ENTER'):
                if self.ctrlNameIs(c,'txtSeek'):
                    txt = self.ctrldi['txtSeek']
                    cbo = self.ctrldi['cboObject']
                    wx.SetCursor(wx.HOURGLASS_CURSOR)
                    cbo.Clear()
                    fillComboData(cbo, 'FDQ_OBJECTS_UNION_GROUPED',['Object'],
                            {'subs':{'Object': txt.Value}})
                    wx.SetCursor(wx.STANDARD_CURSOR)
            elif self.evtTypeIs(t,'COMBOBOX'):
                if self.ctrldi['chkValues'].Value:
                    wx.SetCursor(wx.HOURGLASS_CURSOR)
                    if self.ctrlNameIs(c,'cboField1'):
                        fillComboDataGrouped(self.ctrldi['cboValue1'],
                                'Relations', self.ctrldi['cboField1'].Value)
                    elif self.ctrlNameIs(c,'cboField2'):
                        fillComboDataGrouped(self.ctrldi['cboValue2'],
                                'Relations', self.ctrldi['cboField2'].Value)
                    elif self.ctrlNameIs(c,'cboField3'):
                        fillComboDataGrouped(self.ctrldi['cboValue3'],
                                'Relations', self.ctrldi['cboField3'].Value)
                    wx.SetCursor(wx.STANDARD_CURSOR)

            if self.evtTypeIs(t,'LISTBOX'):

                if self.ctrlNameIs(c,'lstQuery'):
                    self.ctrldi['chkEnableDel'].Value = False
                    self.ctrldi['butDel'].Enable(False)
                    sub = self.ctrldi['lstQuerSub']
                    sub.Clear()
                    self.subprefiltersetli = [elemli[0] for elemli in defgui.prefiltersetsli]

                    if self.ctrldi['lstQuery'].IsSelected(0) == True:   # calendar
                        self.enableControlSets([['tree-filter' ,False],
                                                ['flat-filter' ,True],
                                                ['change-set' ,False]])

                        sub.InsertItems(self.subqueriesli, 0)
                        sub.SetStringSelection(knob_logic.readOption('initial_tasks_query'), True)
                        self.setTasks()
                    elif self.ctrldi['lstQuery'].IsSelected(1) == True: # tree filter

                        self.enableControlSets([['tree-filter' ,True],
                                                ['flat-filter' ,False],
                                                ['change-set' ,True]])

                        self.setTreeFilter()

                    elif self.ctrldi['lstQuery'].IsSelected(2) == True: # flat filter

                        self.enableControlSets([['tree-filter' ,False],
                                                ['flat-filter' ,True],
                                                ['change-set' ,True]])


                        self.setFlatFilter('Flat filter only',{'strings':{'subject':'xyxyxy'}})
                        sub.InsertItems(self.subprefiltersetli, 0)
                        sub.SetSelection(0)
                        self.setFilterFields(self.ctrldi['lstQuerSub'].GetSelection())
#                        self.ctrldi['cboValue2'].SetFocus()


                    elif self.ctrldi['lstQuery'].IsSelected(3) == True: # combined filter

                        self.enableControlSets([['tree-filter' ,True],
                                                ['flat-filter' ,True],
                                                ['change-set' ,True]])
                        self.setTreeFilter()
                        sub.InsertItems(self.subprefiltersetli, 0)
                        sub.SetSelection(0)
                        self.setFilterFields(self.ctrldi['lstQuerSub'].GetSelection())

                elif self.ctrlNameIs(c,'lstQuerSub'):
                    if self.ctrldi['lstQuery'].GetSelection() == 0:   # calendar
                        self.setTasks(self.ctrldi['lstQuerSub'].GetStringSelection())

                    elif self.ctrldi['lstQuery'].GetSelection() in [2,3]: # flat / combined
                        wx.SetCursor(wx.HOURGLASS_CURSOR)
                        self.setFilterFields(self.ctrldi['lstQuerSub'].GetSelection())
                        wx.SetCursor(wx.STANDARD_CURSOR)

            elif self.evtTypeIs(t,'CHECKBOX'):
                if self.ctrlNameIs(c,'chkEnableDel'):
                    valbo = self.ctrldi['chkEnableDel'].Value
                    self.ctrldi['butDel'].Enable(valbo)
                if self.ctrlNameIs(c,'chkManualSql'):
                    pass

        except UnboundLocalError:
            messt = 'The filter-fields were not filled in properly; ' + \
            'please retry.\n' +  '\n' + str(sys.exc_info()[1])
            capst = str(sys.exc_info()[0])
            msg = wx.MessageDialog(self,messt,capst,wx.OK | wx.ICON_WARNING)
            msg.ShowModal()
            msg.Destroy()

        except pysqlite2._sqlite.OperationalError:
            messt = 'The entered filters were not valid; ' + \
            'please retry.\n' +  '\n' + str(sys.exc_info()[1])
            capst = str(sys.exc_info()[0])
            msg = wx.MessageDialog(self,messt,capst,wx.OK | wx.ICON_WARNING)
            msg.ShowModal()
            msg.Destroy()
##            raise
        except:
            messt = 'An unforeseen error occured... \n'  \
                +  '\n' + str(sys.exc_info()[1])
            capst = str(sys.exc_info()[0])
            msg = wx.MessageDialog(self,messt,capst,wx.OK | wx.ICON_ERROR)
            msg.ShowModal()
            msg.Destroy()
##            raise

    def loadTreeFilter(self):
        wx.SetCursor(wx.HOURGLASS_CURSOR)
        messagest = 'Fetching records, please wait...'
        self.parent.sbar.SetStatusText(messagest, 1)

        knob_logic.readBrancheToTable('FDQ_RELATIONS_SORTED3',
            self.ctrldi['cboTrRoot'].Value,
            self.ctrldi['lstDir'].GetStringSelection(),
            int(self.ctrldi['cboTrDepth'].Value),
            includemultiparentbo = self.ctrldi['chkMultiParent'].Value)

        self.parent.mainLisc.readTempRelations()
        rowcountit = self.parent.mainLisc.lisc.GetItemCount()
        messagest = 'Tree-filtered number of records: ' + \
            str(rowcountit)
        self.parent.sbar.SetStatusText(messagest, 1)
        wx.SetCursor(wx.STANDARD_CURSOR)


    def setTasks(self, queryst=''):
        wx.SetCursor(wx.HOURGLASS_CURSOR)
        self.parent._mgr.GetPane('modPanel').Show()
        self.parent._mgr.Update()
        if queryst == '':
            # if a specific query was chosen keep that choice
            sub = self.ctrldi['lstQuerSub']
            if sub.GetCount() > 0:
                if sub.GetStringSelection() in self.subqueriesli:
                    queryst =  sub.GetStringSelection()
                else:
                    queryst = knob_logic.readOption('initial_tasks_query')
            else:
                # else load default-query from the options
                queryst = knob_logic.readOption('initial_tasks_query')
        print "queryst = " + str(queryst)
        if self.ctrldi['cboValue1'].Value == '':
            self.parent.mainLisc.readTasks(queryst)
        else:
            self.parent.mainLisc.readTasks(queryst, self.setFlatCriteria())
        wx.SetCursor(wx.STANDARD_CURSOR)

    def setTreeFilter(self):
        wx.SetCursor(wx.HOURGLASS_CURSOR)
        numli = ['1','2','3','4','5','6','7','8']
        self.ctrldi['cboTrDepth'].Clear()
        self.ctrldi['cboTrDepth'].AppendItems(numli)
        self.ctrldi['cboTrDepth'].Value = '12'

        self.parent._mgr.GetPane('modPanel').Hide()
        self.parent._mgr.Update()

##        knob_logic.deleteTempRelations()    # not handy for switching
        self.parent.mainLisc.readTempRelations()
        messagest = 'Tree-filter shows a temporary copy of ' + \
        'the actual records (latest query shown here)'
        self.parent.sbar.SetStatusText(messagest, 1)

        wx.SetCursor(wx.STANDARD_CURSOR)

    def setFlatCriteria(self, showsqlcritbo = False):
        '''
        UNIT INFO:
         convert the input filter-values to the correct parameter-format
        ADAP HIS:
        -create list of tuples from controls
        -order the list on the operator-type with 'sorted()'
        -cycle thru it to create the criteria-dictionary
            -nulllist expects list, not dict
                -sqlite requires 'isnull' instead of '=null' in select-statements
        '''

        if self.filterFieldsAreSet():

            allcritli = [[],[],[]]
            allcritli[0].append(str(self.ctrldi['cboField1'].Value))
            allcritli[0].append(str(self.ctrldi['cboOperator1'].Value))
            allcritli[0].append(self.ctrldi['cboValue1'].Value)
            allcritli[1].append(str(self.ctrldi['cboField2'].Value))
            allcritli[1].append(str(self.ctrldi['cboOperator2'].Value))
            allcritli[1].append(self.ctrldi['cboValue2'].Value)
            allcritli[2].append(str(self.ctrldi['cboField3'].Value))
            allcritli[2].append(str(self.ctrldi['cboOperator3'].Value))
            allcritli[2].append(self.ctrldi['cboValue3'].Value)

    ##        print allcritli
            sortcritli = sorted(allcritli, key=lambda oper: oper[1])
    ##        print sortcritli

            list_operatorli = ['nullslist', 'nullsnot']
            dict_operatorli = ['strings','subs','beginwith', 'endwith', 
                                'stringsnot', 'subsnot', 
                                'str_bigger',  'str_smaller', 
                                'numbers', 'num_bigger', 'num_smaller']

            lastoperatorst = 'empty'
            for lineli in sortcritli:
    ##            print lastoperatorst
    ##            print lineli
                if lineli[1] in list_operatorli:
                    if lastoperatorst == 'empty':
                        critdi = {lineli[1]:[lineli[0]]}
                    elif lastoperatorst == lineli[1]:
                        critdi[lineli[1]].append(lineli[0])
                    elif lastoperatorst <> lineli[1]:       # new series
                        critdi[lineli[1]] = [lineli[0]]
                    lastoperatorst = lineli[1]

                elif lineli[1] in dict_operatorli:
                    if lastoperatorst == 'empty':
                        critdi = {lineli[1]:{lineli[0]:lineli[2]}}
                    elif lastoperatorst == lineli[1]:
                        critdi[lineli[1]][lineli[0]] = lineli[2]
                    elif lastoperatorst <> lineli[1]:       # new series
                        critdi[lineli[1]] = {lineli[0]:lineli[2]}
                    lastoperatorst = lineli[1]

    ##        print critdi
            if showsqlcritbo:
                self.ctrldi['txtCrit'].Value = pardb.compareClause(critdi, 'where')
            else:
                self.ctrldi['txtCrit'].Value = str(critdi)
                
            return critdi
        else:
            return None


    def setFlatFilter(self, querytypest, critdi):
        wx.SetCursor(wx.HOURGLASS_CURSOR)
        messagest = ''
##        self.parent._mgr.GetPane('modPanel').Hide()
        self.parent._mgr.Update()
        if querytypest == 'Calendar / task-list':
            self.setTasks()
            messagest = isocalendarst
        elif querytypest == 'Flat filter only':
            self.parent.mainLisc.readFlatRelations(querytypest, critdi)
            countit = pardb.rowCountFromParams('', 'Relations', None, critdi)
            messagest = 'Flat-filtered number of records: ' + str(countit)

        elif querytypest == 'Tree and flat filter':
            self.parent.mainLisc.readFlatRelations(querytypest, critdi)
            countit = pardb.rowCountFromParams('', 'RELATIONSTEMP', None, critdi)
            messagest = 'Combined filter - number of records: ' + str(countit)

        self.parent.sbar.SetStatusText(messagest, 1)
        wx.SetCursor(wx.STANDARD_CURSOR)

    def clearControlList(self):
        controlli = ['cboField1','cboOperator1','cboValue1',
                    'cboField2','cboOperator2','cboValue2',
                    'cboField3','cboOperator3','cboValue3',
                    'txtCrit']
        for controlst in controlli:
            self.ctrldi[controlst].Value = ''
            if 'cboValue' in controlst:
                self.ctrldi[controlst].Clear()


    def filterFieldsAreSet(self):
        fieldchainst = self.ctrldi['cboField1'].Value + \
                        self.ctrldi['cboField2'].Value + \
                        self.ctrldi['cboField3'].Value

        if fieldchainst == '':
            return False
        else:
            return True

    def enableControlSets(self, setli2):
        # expecting control-set like: [['tree-filter',True],['flat-filter',False]]
        cset = defgui.defLiconSetsdi
        for listli in setli2:
            self.enableControlList(cset[listli[0]],listli[1])

    def setFilterFields(self, filtersetnumit):
        filtersetli = defgui.prefiltersetsli[filtersetnumit][1]
        it = 1  # walk thru 1-based control-names
        for filterli in filtersetli:
            self.ctrldi['cboField' + str(it)].Value = filterli[0]
            if self.ctrldi['chkValues'].Value:
                fillComboDataGrouped(self.ctrldi['cboValue' + str(it)],
                        'Relations', filterli[0])
            self.ctrldi['cboOperator' + str(it)].Value = filterli[1]
            it += 1
        self.ctrldi['cboValue1'].SetFocus()
        self.ctrldi['cboValue1'].SetFocus()


class leftLiscPanel(lisco.listPanel):

    def __init__(self, parent, ID, pos = wx.DefaultPosition,
            size = wx.DefaultSize):
        lisco.listPanel.__init__(self, parent,ID, pos, size)
        self.parent = parent
##        self.loadDbData()

    def loadDbData(self):
        self.setColumns(defgui.defLiscdi['leftObjects'][1])


    def onAnyEvent(self, evt):
        # overriding parent-class-function
        if evt.GetEventType() == int(wx.EVT_LIST_ITEM_SELECTED._getEvtType()):
            if self.parent.panedi['navPanel'].ctrldi['chkSngClick'].Value:
                # load data on single click
                objst = self.getColText(2)
                self.parent.panedi['navPanel'].readObjects(objst,'fromList')
            else:
                # call a function of modPanel
                self.parent.panedi['modPanel'].readRecord(self.getColText(0))
                messagest = "Record read - " + str(self.getColText(0))
                self.parent.sbar.SetStatusText(messagest, 0)
##            itemit = self.lisc.GetFocusedItem()
##            self.lisc.Select(itemit,0)
        elif evt.GetEventType() == int(wx.EVT_LIST_ITEM_ACTIVATED._getEvtType()):
            # double click
            objst = self.getColText(2)
            self.parent.panedi['navPanel'].readObjects(objst,'fromList')

class rightLiscPanel(lisco.listPanel):
    def __init__(self, parent, ID, pos = wx.DefaultPosition,
            size = wx.DefaultSize):
        lisco.listPanel.__init__(self, parent,ID, pos, size)
        self.parent = parent
##        self.loadDbData()

    def loadDbData(self):
        self.setColumns(defgui.defLiscdi['rightObjects'][1])

    def onAnyEvent(self, evt):
        '''
        ADAP HIS
        - List-row-selection does trigger a read-record for modPanel.
        '''
        if evt.GetEventType() == int(wx.EVT_LIST_ITEM_SELECTED._getEvtType()):
            if self.parent.panedi['navPanel'].ctrldi['chkSngClick'].Value:
                objst = self.getColText(5)
                self.parent.panedi['navPanel'].readObjects(objst,'fromList')
            else:
                # call a function of modPanel
                self.parent.panedi['modPanel'].readRecord(self.getColText(0))
                messagest = "Record read - " + str(self.getColText(0))
                self.parent.sbar.SetStatusText(messagest, 0)
##            # try to unselect the row
##            itemit = self.lisc.GetFocusedItem()
##            self.lisc.Select(itemit,0)
        elif evt.GetEventType() == int(wx.EVT_LIST_ITEM_ACTIVATED._getEvtType()):
            objst = self.getColText(5)
            self.parent.panedi['navPanel'].readObjects(objst,'fromList')


class mainLiscPanel(lisco.listPanel):
    '''
    ADAP HIS
    -use a new lisco-instance
        -setting data mostly is done on the li-control panel (columns and query)
        -direction 5, layer 0,r0,p0
    -pre-hide the pane
    -implement task-list
        -query: rel-tasks
        -set columns and params
    -sync modPanel
        -read to modpanel
        -reread tasklistafter update from modPanel
    -double-click goes to navigator and loads object1 or object2

    ADAP NO

    ADAP FU
    '''

    def __init__(self, parent, ID, pos = wx.DefaultPosition,
            size = wx.DefaultSize):
        lisco.listPanel.__init__(self, parent,ID, pos, size)
        self.parent = parent
##        self.loadDbData()

    def loadDbData(self):
        pass

    def readTasks(self, queryst='FDQ_RELS_TASKS_TWOWEEKS',selcritdi=None):
        self.setColumns(defgui.defLiscdi['taskList'][1])
        self.setDataParams('', queryst, None, selcritdi)

        colBase = wx.ColourDatabase()
        colOne = colBase.Find('PURPLE')
        colTwo = colBase.Find('YELLOW GREEN')
        colThree = colBase.Find('ORANGE')
        colFour = colBase.Find('SEA GREEN')
        colFive = colBase.Find('BROWN')
        colSix = colBase.Find('SLATE BLUE')
        colSeven = colBase.Find('MAROON')
        # further usefull colors: maroon, orange, slate blue

        # color the first 4 weeks; use zfill to match leading zeros
        self.setColorByCondition(wx.BLUE , 1, str(isotu[1]).zfill(2))
        self.setColorByCondition(colFive , 1, str(isotu[1]+1).zfill(2))
        self.setColorByCondition(colSix , 1, str(isotu[1]+2).zfill(2))
        self.setColorByCondition(colSeven , 1, str(isotu[1]+3).zfill(2))

##        datezerost = datest + ' 00:00:00'
        # color today
        self.setColorByCondition(colThree, 5, datest, True)

        dayst = datest[len(datest)-2:]
        dayit = int(dayst)
        frontest = datest[:len(datest)-2]

        tombackst = str(dayit+1)
        if len(tombackst)==1: tombackst = '0' + tombackst
        yesbackst = str(dayit-1)
        if len(yesbackst)==1: yesbackst = '0' + yesbackst

        tomorst = frontest + tombackst
        yesterst = frontest + yesbackst
        self.setColorByCondition(colOne, 5, tomorst, True)
        self.setColorByCondition(colTwo, 5, yesterst, True)
        # color festive days
        self.setColorByCondition(wx.GREEN, 6, 'fe', False)
        print tomorst + ' - ' + yesterst

    def readTempRelations(self):
        self.setColumns(defgui.defLiscdi['tempRelations'][1])
        self.setDataParams('', 'FDQ_RELS_TEMP_QUERY',None, None)

    def readFlatRelations(self, querytypest, critdi):

        if querytypest == 'Flat filter only':
            self.setColumns(defgui.defLiscdi['flatRelations'][1])
            self.setDataParams('', 'FDQ_RELATIONS_FLAT_FILTER',None, critdi)

        elif querytypest == 'Tree and flat filter':
            self.setColumns(defgui.defLiscdi['tempRelations'][1])
            self.setDataParams('', 'FDQ_RELS_TEMP_QUERY',None, critdi)


    def onAnyEvent(self, evt):
        if evt.GetEventType() == int(wx.EVT_LIST_ITEM_SELECTED._getEvtType()):
            # call a function of modPanel
            self.parent.panedi['modPanel'].readRecord(self.getColText(0))
            messagest = "Record read - " + str(self.getColText(0))
            self.parent.sbar.SetStatusText(messagest, 0)
        elif evt.GetEventType() == int(wx.EVT_LIST_ITEM_ACTIVATED._getEvtType()):
            # double click
            self.parent.showPerspective('navigator')
            # called object depends on the querytype
            querytypest = self.parent.panedi['liConPanel'].ctrldi['lstQuery'].GetStringSelection()
            if querytypest == 'Calendar / task-list':
                # col 7 is object2, col 9 obj1 (see defgui.defLiscdi)
                self.parent.panedi['navPanel'].readObjects(self.getColText(7),'external')
            elif querytypest in ['Tree filter only','Tree and flat filter']:
                self.parent.panedi['navPanel'].readObjects(self.getColText(6),'external')
            elif querytypest == 'Flat filter only':
                self.parent.panedi['navPanel'].readObjects(self.getColText(4),'external')
##            elif querytypest == 'Tree and flat filter':
##                return


class paramsLiscPanel(lisco.listPanel):
    '''
    ADAP HIS
    -create deflisc based on param-query
    -create paramModPanel

    ADAP NO

    ADAP FU
    '''

    def __init__(self, parent, ID, pos = wx.DefaultPosition,
            size = wx.DefaultSize):
        lisco.listPanel.__init__(self, parent,ID, pos, size)
        self.parent = parent


    def loadDbData(self, scopest):
        self.scopest = scopest
        self.getAllOptions()
        self.parent.panedi['paramModPanel'].clearOption()

        messagest =  "Select an option from the list"
        self.parent.sbar.SetStatusText(messagest, 0)


    def getAllOptions(self):

        self.setColumns(defgui.defLiscdi['paramsList'][1])
        if self.scopest == 'db-level':
            self.setDataParams('','FDQ_PARAMS_QUERY_LIST_DB',None, None)
            capst = 'Settings on database-level (stored in currently opened db)'
        elif self.scopest == 'sys-level':
            self.setDataParams(db_species.settingsdbst,
                            'FDQ_PARAMS_QUERY_LIST_SYS',None, None)
            capst = 'Settings on program-level (stored in settings_kjx.db)'

        self.parent._mgr.GetPane('paramslisc').Caption(capst)
        self.parent._mgr.Update()

    def onAnyEvent(self, evt):
        if evt.GetEventType() == int(wx.EVT_LIST_ITEM_SELECTED._getEvtType()):
            self.getSingleOption()
        elif evt.GetEventType() == int(wx.EVT_LIST_ITEM_ACTIVATED._getEvtType()):
            pass
##            # double click
##            self.parent.showPerspective('navigator')
##            # col 6 is object1
##            self.parent.panedi['navPanel'].readObjects(self.getColText(6),'external')

    def getSingleOption(self):
        # call a function of paramModPanel
        self.parent.panedi['paramModPanel'].getOption(self.getColText(0), self.scopest)
        messagest = "Record read - " + str(self.getColText(0))
        self.parent.sbar.SetStatusText(messagest, 0)


class paramModPanel(genFrames.genPanel1):
    '''
    ADAP HIS
    - add controls to def
    - read / update parameters (strings and numbers)

    ADAP NO

    ADAP FUT:
    -add error-code
    -check and add all datatypes
    '''

    def __init__(self, parent, ID, pos = wx.DefaultPosition,
            size = wx.DefaultSize, controlsDefDict = None ):
        genFrames.genPanel1.__init__(self, parent,ID, pos,
            size, controlsDefDict)
        self.parent = parent

    def onAnyEvent(self, evt):
        t = evt.GetEventType()
        c = evt.GetId()

        if self.evtTypeIs(t,'BUTTON'):
            if self.ctrlNameIs(c,'butSave'):
                self.updateOption()
        elif self.evtTypeIs(t,'TEXT'):
            pass
        elif self.evtTypeIs(t,'TEXT_COPY'):
            pass
        elif self.evtTypeIs(t,'TEXT_ENTER'):
            if self.ctrlNameIs(c,'txtSeek'):
                pass
        elif self.evtTypeIs(t,'COMBOBOX'):
            pass
        if self.evtTypeIs(t,'LISTBOX'):
            if self.ctrlNameIs(c,'lstQuery'):
                pass

    def clearOption(self):
        self.ctrldi['labParidValue'].SetLabel('')
        self.ctrldi['labNameValue'].SetLabel('')
        self.ctrldi['labDescripValue'].SetLabel('')
        self.ctrldi['labDTypeValue'].SetLabel('')
        self.ctrldi['cboParamValue'].Clear()
        self.ctrldi['cboParamValue'].Value = ''
        self.ctrldi['labDefaultValue'].SetLabel('')


    def getOption(self, paramid, scopest):
        '''
        ADAP HIS
        -retrieves data-cursor based on list-control-focus and ID
        -use readDictFromParams on the params-table
            -use pardb.py
                -use '' as default database-name
        -adapt for pick-list and defaults
            v-reorder the fields in the table for better management
                v-update the sqlite-tool-functionality-table
            v-create extra field to separate between db and sys parameters
                v-create queries to show the db or sys-stuff
            v-fill in pick-lists and defaults
            v-make code to show the stuff
        -add for program-level options stored in settings_kjx.db
            -read paramliscpanel from other database
                v-adapt code in lisco; setdatabase is not usefull
        v-clear pane on load

        ADAP NO


        ADAP FU
        '''

##        rowdi = pardb.readDictFromParams('','PARAMS', None,
##                    {'strings':{'ParamID':paramid}})
        self.scopest = scopest
        if self.scopest == 'db-level':
            rowdi = pardb.readDictFromParams('','PARAMS', None,
                        {'strings':{'ParamID':paramid}})
        elif self.scopest == 'sys-level':
            rowdi = pardb.readDictFromParams(db_species.settingsdbst,'PARAMS', None,
                        {'strings':{'ParamID':paramid}})


##        fieldli = jodb.getFieldList('Relations')
##        datatypeli = jodb.getDataTypeList('PARAMS')
##        for row in curli: # only 1 row here

        self.ctrldi['labParidValue'].SetLabel(str(rowdi['ParamID']))
        self.ctrldi['labNameValue'].SetLabel(str(rowdi['Name']))
        self.ctrldi['labDescripValue'].SetLabel(str(rowdi['Description']))

        datatypest = str(rowdi['Datatype'])
        self.ctrldi['labDTypeValue'].SetLabel(datatypest)
        paramvalue = rowdi[datatypest]
##        print 'paramvalue - ' + str(paramvalue)

        defaultvalst = str(rowdi[datatypest[:3] + '_DEF'])
        self.ctrldi['labDefaultValue'].SetLabel(defaultvalst)

        self.ctrldi['cboParamValue'].Clear()
        self.ctrldi['cboParamValue'].Value = str(paramvalue)
        picklist = str(rowdi[datatypest[:3] + '_LST'])
##        print 'picklist - ' + str(picklist)
##        print len(picklist)
        if picklist in ['',None,'None']:
##            print 'none - ' + defaultvalst
            self.ctrldi['cboParamValue'].Append(defaultvalst)
        else:
            pickli = picklist.split(';;')
            self.ctrldi['cboParamValue'].AppendItems(pickli)


    def updateOption(self):
        paramidst = self.ctrldi['labParidValue'].GetLabel()
        datatypest = str(self.ctrldi['labDTypeValue'].GetLabel())
        valst = self.ctrldi['cboParamValue'].Value

        if self.scopest == 'db-level':
            dbst = ''
        elif self.scopest == 'sys-level':
            dbst = db_species.settingsdbst

        editablebo = bool(pardb.readDictFromParams(dbst,'PARAMS', None,
                    {'strings':{'ParamID':paramidst}})['IsEditableByUser'])

        if editablebo == True:
            if datatypest == 'STRINGS':
                pardb.updateFromParams(dbst, 'PARAMS',{'strings':{datatypest:valst}},
                    {'strings':{'ParamID':paramidst}})
            elif datatypest == 'INTEGERS':
                pardb.updateFromParams(dbst, 'PARAMS',{'numbers':{datatypest: int(valst)}},
                    {'strings':{'ParamID':paramidst}})
            elif datatypest == 'DECIMALS':
                pardb.updateFromParams(dbst, 'PARAMS',{'numbers':{datatypest: float(valst)}},
                    {'strings':{'ParamID':paramidst}})
            elif datatypest == 'BOOLEANS':
                pardb.updateFromParams(dbst, 'PARAMS',{'numbers':{datatypest: int(valst)}},
                    {'strings':{'ParamID':paramidst}})

            messagest = 'Parameter-value has been updated - ParamID: ' + paramidst
        else:
            messagest = 'This parameter can not be edited by the user: '  + paramidst
        self.parent.sbar.SetStatusText(messagest, 1)


class treecPanel(treeco.treePanel):
    def __init__(self, parent, ID, pos = wx.DefaultPosition,
            size = wx.DefaultSize):
        treeco.treePanel.__init__(self, parent,ID, pos, size)
        self.parent = parent


    def onAnyEvent(self, evt):
        try:
            if evt.GetEventType() == int(wx.EVT_TREE_SEL_CHANGED._getEvtType()):
                # read objects based on selected item
                curItem = self.treec.GetSelection()
                pyDatali = self.treec.GetPyData(curItem)
                valuest = pyDatali[0]
                self.parent.panedi['navPanel'].readObjects(valuest,'fromtree')

                # call a function of modPanel
                idvalueit = pyDatali[1]
                self.parent.panedi['modPanel'].readRecord(idvalueit)
                messagest = "Record read - " + str(idvalueit)
                self.parent.sbar.SetStatusText(messagest, 0)


    ##            try:
    ##                parentItem = self.treec.GetItemParent(curItem)
    ##                parentvaluest = self.treec.GetPyData(parentItem)
    ##                self.parent.panedi['navPanel'].readObjects(parentvaluest,'fromtree')
    ##            except:
    ##                print 'no parent available'

            elif evt.GetEventType() == int(wx.EVT_TREE_ITEM_ACTIVATED._getEvtType()):
                print 'activated'
            elif evt.GetEventType() == int(wx.EVT_LEFT_DCLICK._getEvtType()):
                maxdepthit = int(self.parent.panedi['navPanel'].ctrldi['cboTrDepth'].Value)

                if self.parent.panedi['navPanel'].ctrldi['chkTrLeft'].Value:
                    if self.parent.panedi['navPanel'].ctrldi['chkUseFilter'].Value:
                        self.parent.treePane.loadTree(
                            'FDQ_RELS_TREE_LEFT','append',maxdepthit + 3 ,'', 
                            extracritdi = globala.navcritdi)
                    else:
                        self.parent.treePane.loadTree(
                            'FDQ_RELS_TREE_LEFT','append',maxdepthit + 3 ,'')
                    mst = 'Left-loading branche  - please wait....'
                    self.parent.sbar.SetStatusText(mst, 1)

                else:
                    mst = 'Loading branche with query-depth ' + str(maxdepthit) \
                        + ' - please wait....'
                    self.parent.sbar.SetStatusText(mst, 1)
                    if self.parent.panedi['navPanel'].ctrldi['chkHide'].Value:
                        tablest = 'FDQ_RELS_TREE_RIGHT_OPEN_TASKS'
                    else:
                        tablest = 'FDQ_RELS_TREE_RIGHT'
                    
                    if self.parent.panedi['navPanel'].ctrldi['chkUseFilter'].Value:
##                        print 'globala.navcritdi = ' + str(globala.navcritdi)
                        self.parent.treePane.loadTree(tablest,'append', maxdepthit, '', 
                                                      extracritdi = globala.navcritdi)
                    else:
                        self.parent.treePane.loadTree(tablest,'append',maxdepthit, '')
                self.parent.sbar.SetStatusText(isocalendarst, 1)

            elif evt.GetEventType() == int(wx.EVT_TREE_BEGIN_DRAG._getEvtType()):
                print 'begin drag!!!'
                wx.TreeEvent.Allow(evt)
                # sample the begin-linked ID (defines where-clause)
                curItem = evt.GetItem()
                pyDatali = self.treec.GetPyData(curItem)
                self.id_dragbegin = pyDatali[1]
                # also sample the parent, just for informational echoing
                parItem = self.treec.GetItemParent(curItem)
                pyParDatali = self.treec.GetPyData(parItem)
                self.id_dragparent = pyParDatali[1]
                print self.id_dragbegin
    ##            print self.id_dragparent
                # store the begin-node-item class-wide
                self.treeNode_dragBegin = curItem

            elif evt.GetEventType() == int(wx.EVT_TREE_END_DRAG._getEvtType()):
                print 'end drag!!!'
                try:
                    # sample the end-linked child (becomes the new parent or object1)
                    curItem = evt.GetItem()
                    self.treeNode_dragEnd = curItem
                    pyDatali = self.treec.GetPyData(curItem)
                    endchildst = pyDatali[0]
                    endchildidit = pyDatali[1]
                    print endchildst
                    if endchildidit <> self.id_dragbegin:
                        mst = 'Re-linking...please wait...'
                        self.parent.sbar.SetStatusText(mst, 1)
                        # do database-update
                        pardb.updateFromParams('', 'Relations',
                                {'strings':{'object1':endchildst,
                                            'modDate': str(datetime.today())[:19]}},
                                {'numbers':{'RelID':self.id_dragbegin}})
                        # remove the begin-node
                        self.treec.Delete(self.treeNode_dragBegin)
                        # repopulate the end-node
                        if self.parent.panedi['navPanel'].ctrldi['chkHide'].Value:
                            tablest = 'FDQ_RELS_TREE_RIGHT_OPEN_TASKS'
                        else:
                            tablest = 'FDQ_RELS_TREE_RIGHT'
                        if self.parent.panedi['navPanel'].ctrldi['chkUseFilter'].Value:
                            self.loadTree(tablest,'appendspecific', 2, "" , curItem, 
                                          extracritdi = globala.navcritdi)
                        else:
                            self.loadTree(tablest,'appendspecific', 2, "" , curItem)
                        mst = 'Item ' + str(self.id_dragbegin) + ' was re-linked from ' \
                             + str(self.id_dragparent) + ' to ' + str(endchildidit)
                        self.parent.sbar.SetStatusText(mst, 1)
                    else:
                        mst = 'Can not drop on self; retry..'
                        self.parent.sbar.SetStatusText(mst, 1)
                except wx._core.PyAssertionError:
                    mst = 'Invalid drop-target; retry..'
                    self.parent.sbar.SetStatusText(mst, 1)
                    print mst
                except:
                    print 'Unanticipated error'
        except:
            messt = 'An unforeseen error occured... \n'  \
                +  '\n' + str(sys.exc_info()[1])
            capst = str(sys.exc_info()[0])
            msg = wx.MessageDialog(self,messt,capst,wx.OK | wx.ICON_ERROR)
            msg.ShowModal()
            msg.Destroy()


class exportDialog(wx.Dialog):
    '''
    ADAP HIS
    -file-types
        -output
            -calendar file
        -input
            -new relations or standard tasks
    -design the gui
        -use modal screens (to avoid number of unexpected influences)
        -use separate screens for export and import
        -make quick-button to do default-exchanges
        -describe the exchange-process
            -output
                -use and set query-def (is being sampled as source)
                -select output-format (prepare for other destinations, like
                 print or .xls)
                -destination
                -create the output-file
            -input
                -select input-file
                -select file-format
                -select input-mode
                -import
    -create the gui
        -technology: use wx.dialog and genPanel (from genFrames)
            -test this in genFrames
        -create a def in defgui

    ADAP NO
    '''

    def __init__ (self, parent, ID, title="",
            pos=wx.DefaultPosition, size=wx.DefaultSize,
            style = wx.DEFAULT_DIALOG_STYLE):
        wx.Dialog.__init__(self, parent, ID, title, pos, size, style)

        self.parent = parent

        pan = exportPanel(self, -1,
            controlsDefDict = defDialogdi['exportPanel'])

        # wx.dialog does not autosize panels a.o.t. frames
        self.mysizer = wx.BoxSizer(wx.VERTICAL)
        self.mysizer.Add(pan, 1, wx.EXPAND|wx.ALL, 5)
        self.SetSizer(self.mysizer)
        self.mysizer.Fit(self)     # shrink dialog-size to minimal

class exportPanel(genFrames.genPanel1):
    '''
    ADAP HIS
    v-add the needy options in the db
    v-load the options in the panel
    v-add export-button to query-panel
    v-create definition-file
    v-research thruport-code
    v-reuse exporting code
    -adaptations
        v-call somehow setFlatCriteria from liconpanel
        v-set 'setFlatCriteria' to None if no criteria-fields are entered
        v-calling-location determines outcome of some vars - adapted call-method
        v-substitute definition-file for defTexchangedi-definition
        v-use task-query from licon-panel plus matching definition-file
        -prepare other combinations of queries and def-files
            v-make a db-param for every def-file
            v-sample query to pick the def-file
            v-prepare query and def-file combinations
        v-real. choose def-file
        v-give status-info and test debug wrong inputs
            v-theorize error-handling
        v-prefix a header-rows
    -add button open targetfolder
    -adjust scopes db to sys

    ADAP NO

    ADAP FUT
    -realize column-reordering (thru def-files)
    '''


    def __init__(self, parent, ID, pos = wx.DefaultPosition,
            size = wx.DefaultSize, controlsDefDict = None ):
        genFrames.genPanel1.__init__(self, parent,ID, pos,
            size, controlsDefDict)
        self.parent = parent
        self.loadData()

    def loadData(self):

        self.ctrldi['labStatus'].SetForegroundColour(wx.BLUE)
        self.messagenomailst = \
            "Export your query-data to a text-file using the definition-file\n" + \
            "Prefix, Project and Author (=imported-from) are obligatory.\n" + \
            "If you want your export to be importable in another database:\n" + \
            "- width of object1 and object2 in the def.-file must be equal.\n" + \
            "- if data-lenght is greater then defined, data will clipped."
        self.ctrldi['labStatus'].SetLabel(self.messagenomailst )
        self.messageusemailst = \
            "You can email your text-file directly from Knobjex.\n" + \
            "Firstly, you must save the export-file to disk (button Export).\n" + \
            "You still need your default email-client to receive emails."

        self.ctrldi['txtFoPaVal'].Value = knob_logic.readOption('export_folder_path')
        self.ctrldi['txtPrefix'].Value = knob_logic.readOption('export_file_prefix')
        definitionfolderst = knob_logic.readOption('export_definition_folder','sys')
        if str(definitionfolderst) == '':
            definitionfolderst = curModuleSubDir('other_files')
        self.ctrldi['txtDeFoPaVal'].Value = definitionfolderst

        # set the right export-definition-file
        self.querytypest = self.parent.parent.panedi['liConPanel'].ctrldi['lstQuery'].GetStringSelection()
        exportdefparamst = defgui.mapQueryToExportDefParamdi[self.querytypest][0]
        self.ctrldi['txtDeFiNaVal'].Value = knob_logic.readOption(exportdefparamst,'sys')

        self.ctrldi['chkAttach'].Value = True

        # email-fields
        self.ctrldi['chkEnableMail'].Value = False
        self.mailcontrolsli = ["labName","labField","labEmail","cboName","cboField",
            "cboEmail","butAddToGroup","txtEmailGroup","butSaveGroup",
            "labSubject","txtSubject","labText","txtText","chkAttach","butEmail"]

        self.showControlList(self.mailcontrolsli, False)

        self.contacttablest = knob_logic.readOption('root_of_contacts','db')
        self.emailfieldst = knob_logic.readOption('email_field','db')
        fillComboData(self.ctrldi['cboName'], 'Relations',
            ['Object2','Object1','Relation'],
            {'strings':{'Object1':self.contacttablest}})
        self.ctrldi['cboField'].Value = knob_logic.readOption('email_field','db')
        fillComboData(self.ctrldi['cboEmail'], 'Relations',
            ['Object2','Object1','Relation'],
            {'subs':{'Relation':self.emailfieldst}})
        septypeli = ['sep-current-os', 'sep-windows', 'sep-linux-or-newmac', 
                        'sep-oldmac']
        self.ctrldi['cboLineSep'].AppendItems(septypeli)
        self.ctrldi['cboLineSep'].SetSelection(0)
               

    def onAnyEvent(self, evt):
        t = evt.GetEventType()
        c = evt.GetId()

        if self.evtTypeIs(t,'BUTTON'):
            if self.ctrlNameIs(c,'butPreview'):
                filledli = ['txtFoPaVal','txtPrefix','txtFromAuthor','txtProject']
                noforbiddenli = ['txtPrefix','txtProject','txtFromAuthor']
                filledinbo = self.validateControlList(filledli,'filled-in')
                noforbiddenbo = self.validateControlList(noforbiddenli,
                            'no-forbidden-tokens',[' '])

                if filledinbo and noforbiddenbo:
                    self.ctrldi['txtPreviewName'].Value = self.concatenateNameParts(
                        '_',
                        [self.ctrldi['txtPrefix'].Value,
                        self.ctrldi['txtProject'].Value,
                        self.ctrldi['txtFromAuthor'].Value,
                        defgui.mapQueryToExportDefParamdi[self.querytypest][1],
                        jotools.currentDateTime(True) ])
                else:
                    mest = 'All below fields must be filled in without spaces:\n' + \
                            str(noforbiddenli)
##                    self.ctrldi['labStatus'].SetLabel(mest)
                    showMessage(self,mest,'Validation file-name')

            elif self.ctrlNameIs(c,'butChooseFile'):
                self.ctrldi['txtDeFiNaVal'].Value = \
                    self.openFile_Text(self.ctrldi['txtDeFoPaVal'].Value)

            elif self.ctrlNameIs(c,'butExport'):
                try:
                    if self.validateControlList(['txtPreviewName'],'filled-in'):
                        wx.SetCursor(wx.HOURGLASS_CURSOR)
                        self.ctrldi['labStatus'].SetLabel('Starting export...')
                        queryst = defgui.mapQueryToExportDefParamdi[self.querytypest][2]
                        if self.querytypest == 'Tree filter only':
                            addcritdi = None
                        else:
                            addcritdi =  self.parent.parent.panedi['liConPanel'].setFlatCriteria()

                        exportfolderpathst = self.ctrldi['txtFoPaVal'].Value
                        exportfilenamest = self.ctrldi['txtPreviewName'].Value
                        deffolderst = self.ctrldi['txtDeFoPaVal'].Value
                        deffilest = self.ctrldi['txtDeFiNaVal'].Value
                        lineseptypest = self.ctrldi['cboLineSep'].Value

                        thruport.exportGeneric(exportfolderpathst, exportfilenamest,
                                                deffolderst, deffilest,
                                                queryst,addcritdi, lineseptypest)
                        messt = 'Export completed succesfully.\nReview you file at the export-folder-path.'
                        self.ctrldi['labStatus'].SetLabel(messt)
                        wx.SetCursor(wx.STANDARD_CURSOR)
                    else:
                        showMessage(self,'Press prepare-button to create file-name.',
                            'Validation file-name')

                except:

                    customst = 'The operation could not be completed..' + \
                        '\nPlease check that below files and paths are correct. ' + \
                        '\n(ingnore double-slashes)'
                    messagest = customst +  '\n\n' + str(sys.exc_info()[0])+ \
                     '\n' + str(sys.exc_info()[1])
                    print messagest
                    showMessage(self,messagest,'Error',wx.ICON_WARNING)
                    messt = 'Export failed. Export-file may be corrupted or empty. Please retry..'
                    self.ctrldi['labStatus'].SetLabel(messt)
                    wx.SetCursor(wx.STANDARD_CURSOR)


            elif self.ctrlNameIs(c,'butOpenTargetFolder'):
                wx.SetCursor(wx.HOURGLASS_CURSOR)
                filepathst = self.ctrldi['txtFoPaVal'].Value
                os_species.runFileAssociatedApp(filepathst)
##                jotools.openUrl(filepathst)
                wx.SetCursor(wx.STANDARD_CURSOR)

            elif self.ctrlNameIs(c,'butEmail'):
                try:
                    wx.SetCursor(wx.HOURGLASS_CURSOR)
                    messt = 'Now sending email...'
                    self.ctrldi['labStatus'].SetLabel(messt)
                    if not self.ctrldi['chkAttach'].Value:
                        exportfilepath = ''
                        print 'no attachment'
                    else:
                        normPath = os.path.normpath(self.ctrldi['txtFoPaVal'].Value)
                        exportfilepath = os.path.join(normPath,  self.ctrldi['txtPreviewName'].Value)
                        print 'with attachment'
                        print exportfilepath
                    bodytekst = str(self.ctrldi['txtText'].Value) + \
                        '\n\n\nThis email was sent thru Knobjex InfoManager.' + \
                        '\nDownload the program to view the text-file natively.' + \
                        '\nGoogle for Knobjex to find it.'
                    if len(self.ctrldi['txtEmailGroup'].Value) == 0:
                        emailaddresst = self.ctrldi['cboEmail'].Value
                    else:
                        emailaddresst = self.ctrldi['txtEmailGroup'].Value
                    emailthis.emailMessage(knob_logic.readOption('from_email_user'),
                        knob_logic.readOption('from_email_password'),
                        emailaddresst,
                        self.ctrldi['txtSubject'].Value,
                        bodytekst,
                       knob_logic.readOption('smtp_server'),
                       exportfilepath)
                    messt = 'Email has been sent!'
                    self.ctrldi['labStatus'].SetLabel(messt)
                    wx.SetCursor(wx.STANDARD_CURSOR)
                except:
                    customst = 'The operation could not be completed..' + \
                        '\n(For files, check that below files and paths are correct. ' + \
                        '\n Ignore double-slashes)'
                    messagest = customst +  '\n\n' + str(sys.exc_info()[0])+ \
                     '\n' + str(sys.exc_info()[1])
                    print messagest
                    showMessage(self,messagest,'Error',wx.ICON_WARNING)
                    messt = 'Email-sending failed...'
                    self.ctrldi['labStatus'].SetLabel(messt)
                    wx.SetCursor(wx.STANDARD_CURSOR)
            elif self.ctrlNameIs(c,'butAddToGroup'):
                # add email-adres to group
                self.ctrldi['txtEmailGroup'].Value = self.concatenateEmailAddresses(
                                            self.ctrldi['txtEmailGroup'].Value,
                                            self.ctrldi['cboEmail'].Value)

            elif self.ctrlNameIs(c,'butSaveGroup'):
                # save the currently composed group as record
                di = {}
                messagest = 'Please enter the name under which the email-group ' \
                            + 'must be stored.'
                dlg = wx.TextEntryDialog(self, messagest, 'Email-group-name',
                        'new email-group')

                if dlg.ShowModal() == wx.ID_OK:
                    # first record
                    print 'first rec'
                    di['Object1'] = self.contacttablest
                    di['Relation'] = 'record'
                    di['Object2']= str(dlg.GetValue())
                    di['ModDate'] = str(datetime.today())[:19]
                    di['Source'] = knob_logic.readOption('default_source')
                    di['CreaDate'] = str(datetime.today())[:19]
                    defaultcreatorst =  knob_logic.readOption('default_creator')
                    if defaultcreatorst == 'auto':
                        di['Creator'] = os.getenv('COMPUTERNAME') + \
                            ' / ' + os.getenv('USERNAME') + ' / ' + di['Source']
                    else:
                        di['Creator'] = defaultcreatorst + ' / ' + di['Source']
##                    print di
                    pardb.addnewFromParams('', 'Relations', di)

                    # second record
                    di['Object1'] = str(dlg.GetValue())
                    di['Relation'] = knob_logic.readOption('email_field','db')
                    di['Object2']= str(self.ctrldi['txtEmailGroup'].Value)
##                    print di
                    pardb.addnewFromParams('', 'Relations', di)
                    showMessage(self,'Email-group "' + str(di['Object1']) + \
                        '" added to "' + str(self.contacttablest) + '"',
                        'Group-addition')
                    dlg.Destroy()


        elif self.evtTypeIs(t,'CHECKBOX'):
            if self.ctrlNameIs(c,'chkEnableMail'):
                valbo = self.ctrldi['chkEnableMail'].Value
                self.showControlList(self.mailcontrolsli, valbo)
                self.parent.mysizer.Fit(self.parent)     # adjust dialog-size to minimal
                if valbo:
                    self.ctrldi['labStatus'].SetLabel(self.messageusemailst)
                else:
                    self.ctrldi['labStatus'].SetLabel(self.messagenomailst)

        elif self.evtTypeIs(t,'TEXT'):
            pass
        elif self.evtTypeIs(t,'TEXT_COPY'):
            pass
        elif self.evtTypeIs(t,'TEXT_ENTER'):
            # query export-email fields
            if self.ctrlNameIs(c,'cboName'):
                fillComboData(self.ctrldi['cboName'], 'Relations',
                    ['Object2','Object1','Relation'],
                    {'strings':{'Object1':self.contacttablest},
                    'subs':{'Object2':self.ctrldi['cboName'].Value}})
            if self.ctrlNameIs(c,'cboEmail'):
                fillComboData(self.ctrldi['cboEmail'], 'Relations',
                    ['Object2','Object1','Relation'],
                    {'subs':{'Relation':self.emailfieldst,
                        'Object2':self.ctrldi['cboEmail'].Value}})

        elif self.evtTypeIs(t,'COMBOBOX'):
            if self.ctrlNameIs(c,'cboName'):
                fillComboData(self.ctrldi['cboEmail'], 'Relations',
                    ['Object2','Object1','Relation'],
                    {'subs':{'Relation':self.emailfieldst},
                    'strings':{'Object1':self.ctrldi['cboName'].Value}})
                self.ctrldi['cboEmail'].SetSelection(0)

    def openFile_Text(self, openingfolderst):
            dlg = wx.FileDialog(
                self, message="Choose your text-file (*.txt)",
                defaultDir=openingfolderst,
                defaultFile="",
                wildcard="text-files (*.txt)|*.txt|all files (*.*)|*.*",
                style=wx.OPEN | wx.CHANGE_DIR | wx.FD_FILE_MUST_EXIST
                )
            pathst = ''
            if dlg.ShowModal() == wx.ID_OK:
##                pathst = dlg.GetPath()
                pathst = dlg.GetFilename()
                print pathst
            dlg.Destroy()
            return pathst

    def concatenateNameParts(self, separatorst, namepartli):
        namest = separatorst.join(namepartli)
        namest += '.txt'
        return namest

    def concatenateEmailAddresses(self, firstchainst, nextchainst):
        '''
        UNIT INFO
        concatenate email-chains.
        (assume that composing chains have no trailing separators)
        '''

        if len(firstchainst) == 0:
            totalchainst = nextchainst
        else:
            totalchainst = firstchainst + "," + nextchainst

        return totalchainst


class importDialog(wx.Dialog):
    '''
    ADAP NO
    '''
    def __init__ (self, parent, ID, title="",
            pos=wx.DefaultPosition,
            size=wx.DefaultSize, style = wx.DEFAULT_DIALOG_STYLE
            ,sourcepathst = '', targetpathst = '',
            wipetargetbo = False, infost = ''):

        wx.Dialog.__init__(self, parent, ID, title, pos, size, style)

        pan = importPanel(self, -1,
            controlsDefDict = defDialogdi['importPanel'])
        pan.ctrldi['txtSource'].Value = sourcepathst
        pan.ctrldi['txtTarget'].Value = targetpathst
        pan.ctrldi['chkEmpty'].Value = wipetargetbo
        if infost <> '':
            pan.ctrldi['labStatus'].SetLabel(infost)

        # wx.dialog does not autosize panels aot frames
        sizer = wx.BoxSizer(wx.VERTICAL)
        sizer.Add(pan, 1, wx.EXPAND|wx.ALL, 5)
        self.SetSizer(sizer)
        sizer.Fit(self)     # shrink dialog-size to minimal

class importPanel(genFrames.genPanel1):
    '''
    ADAP HIS
    -choose file-dialogs
    -analysis; do this in pumpupthebase.py
        -split up the analysis-label and put them under the db-textboxes
        -info-types
            -versions
            -number of recs
    -set conditions
        -pre-empty
    -update status-messages
    -test and debug import-code
    -adapt screen for importing text-files
        v-paramatrize Choose source-file to use text-files
    v-add error-handling

    ADAP NO

    ADAP FUT
    -use dialog/panel parameter to load the proper import-type
    (normally text-file but with old db do load the db-type)
    -mark imported recs as selected
    -research possib of reporting progress
    -investigate the hiding of controls
    '''


    def __init__(self, parent, ID, pos = wx.DefaultPosition,
            size = wx.DefaultSize, controlsDefDict = None ):
        genFrames.genPanel1.__init__(self, parent,ID, pos,
            size, controlsDefDict)
        self.parent = parent
        self.loadData()

    def loadData(self):
        cboIT  = self.ctrldi['cboImType']
        cboIT.AppendItems(['Database','Text-file'])
        cboIT.SetSelection(0)
##        cboIT.Enable(False)
        self.ctrldi['labAnaSource'].SetForegroundColour(wx.BLUE)
        self.ctrldi['labAnaTarget'].SetForegroundColour(wx.BLUE)
        self.ctrldi['labStatus'].SetForegroundColour(wx.BLUE)

        self.setPanelControls(cboIT.Value)
##        self.ctrldi['chkMark'].Enable(False)
        self.ctrldi['txtColSep'].Value = \
            knob_logic.readOption('column_separator','sys')
        septypeli = ['sep-current-os', 'sep-windows', 'sep-linux-or-newmac', 
                        'sep-oldmac']
        self.ctrldi['cboLineSep'].AppendItems(septypeli)
        self.ctrldi['cboLineSep'].SetSelection(0)


    def onAnyEvent(self, evt):
        t = evt.GetEventType()
        c = evt.GetId()
        try:
            if self.evtTypeIs(t,'BUTTON'):
                if self.ctrlNameIs(c,'butSource'):
                    importtypest = self.ctrldi['cboImType'].Value
                    filepathst = self.openFile(importtypest)
                    self.ctrldi['txtSource'].Value = filepathst
                    if importtypest == 'Text-file':
                        if filepathst.count('_') >= 2:
                            self.ctrldi['txtProject'].Value = filepathst.split('_')[1]
                            self.ctrldi['txtFromAuthor'].Value = filepathst.split('_')[2]

                elif self.ctrlNameIs(c,'butTarget'):
                    self.ctrldi['txtTarget'].Value = self.openFile(self.ctrldi['cboImType'].Value)
                elif self.ctrlNameIs(c,'butAnalyse'):
                    importtypest = self.ctrldi['cboImType'].Value
                    if importtypest == 'Database':
                        sourceinfost = pumpupdabase.getInfoFromDatabase(self.getSourceFile())
                        self.ctrldi['labAnaSource'].SetLabel(sourceinfost)
                        targetinfost = pumpupdabase.getInfoFromDatabase(self.getTargetFile())
                        self.ctrldi['labAnaTarget'].SetLabel(targetinfost)
                    elif importtypest == 'Text-file':
                        lineseptypest = self.ctrldi['cboLineSep'].Value
                        messagest = thruport.probeImportTextFile(self.getSourceFile(),
                                        str(self.ctrldi['txtColSep'].Value), 
                                        lineseptypest)
                        showMessage(self, messagest, 'File-info')
                elif self.ctrlNameIs(c,'butImport'):
                    importtypest = self.ctrldi['cboImType'].Value
                    if importtypest == 'Database':
                        src = self.ctrldi['labAnaSource'].GetLabel()
                        tar = self.ctrldi['labAnaTarget'].GetLabel()
                        if ('db_version' in src) and ('db_version' in tar):
                            if self.ctrldi['chkEmpty'].Value:
                                statust = 'Deleting tables of target-database...'
                                self.ctrldi['labStatus'].SetLabel(statust)
                                pumpupdabase.deleteTableList(self.getTargetFile(),
                                ['RELATIONS','RELATIONSTEMP','HISTORY','PATHWAYS'])
                            pumpupdabase.resetAutoIncrement(self.getTargetFile(),
                                ['RELATIONS'])
                            statust = 'Transfering data...this may take some time.. \n' + \
                                        'Get some coffee...'
                            self.ctrldi['labStatus'].SetLabel(statust)
                            pumpupdabase.pumpAllTables(['Relations', 'PARAMS'],
                                            'sqlite3', self.getSourceFile(),
                                            'sqlite3', self.getTargetFile())
                            statust = 'Transfer complete. You can now use the new target-db. \n' + \
                                        'New target-info: \n\n' + \
                                        pumpupdabase.getInfoFromDatabase(self.getTargetFile())
                            self.ctrldi['labStatus'].SetLabel(statust)
                        else:
                            statust = 'Either source or target database is invalid.\n' + \
                                        'Re-choose your databases.'
                            self.ctrldi['labStatus'].SetLabel(statust)
                    elif importtypest == 'Text-file':
                        controlstobefilledli = ['txtSource','txtProject',
                            'txtFromAuthor','txtColSep']
                        if self.validateControlList(controlstobefilledli, 'filled-in'):
                            statust = 'Starting import...'
                            self.ctrldi['labStatus'].SetLabel(statust)
                            lineseptypest = self.ctrldi['cboLineSep'].Value
                            
                            if thruport.importGeneric(self.getSourceFile(),
                                    str(self.ctrldi['txtProject'].Value),
                                    str(self.ctrldi['txtFromAuthor'].Value),
                                    str(self.ctrldi['txtColSep'].Value),
                                    lineseptypest):
                                statust = '\nText-file has been imported. ' \
                                            + 'Query to review the results.'
                            else:
                                statust = '\nNo text-lines have been imported. ' \
                                    + 'The file seems imcompatible or empty.'
                            self.ctrldi['labStatus'].SetLabel(statust)
                        else:
                            showMessage(self, 'The following fields be must filled in:' \
                                + '\n\n' + str(controlstobefilledli), 'Warning')

            elif self.evtTypeIs(t,'TEXT'):
                pass
            elif self.evtTypeIs(t,'TEXT_COPY'):
                pass
            elif self.evtTypeIs(t,'TEXT_ENTER'):
                pass
            elif self.evtTypeIs(t,'COMBOBOX'):
                if self.ctrlNameIs(c,'cboImType'):
                    valst = self.ctrldi['cboImType'].Value
                    self.setPanelControls(valst)
        except IOError:
            customst = 'The file to import seems to be invalid.'
            messagest = customst +  '\n\n' + str(sys.exc_info()[0])+ \
             '\n' + str(sys.exc_info()[1])
            print messagest
            showMessage(self,messagest,'Error',wx.ICON_WARNING)
            messt = 'Import failed. Import-file may be incompatible. Please retry..'
            self.ctrldi['labStatus'].SetLabel(messt)
        except:
            customst = 'The operation was interrupted.'
            messagest = customst +  '\n\n' + str(sys.exc_info()[0])+ \
             '\n' + str(sys.exc_info()[1])
            print messagest
            showMessage(self,messagest,'Error',wx.ICON_WARNING)
            messt = 'Import failed. Import-file may be incompatible. Please retry..'
            self.ctrldi['labStatus'].SetLabel(messt)
##            raise

    def setPanelControls(self,importtypest):
        # set the right controls
        databasesetli = ['labTarget', 'txtTarget','butTarget','chkEmpty']
        textfilesetli = ['labProject', 'txtProject', 'labFromAuthor','txtFromAuthor',
                        'labColSep','txtColSep','labLineSep','cboLineSep']

        if importtypest == 'Database':
            self.showControlList(databasesetli, True)
            self.showControlList(textfilesetli, False)
            self.ctrldi['labSource'].SetLabel('Source-database:')
            self.ctrldi['txtTarget'].Value = ''
            self.ctrldi['butAnalyse'].SetLabel('Probe the databases')

            self.ctrldi['labAnaSource'].SetLabel('No valid source-info yet')
            self.ctrldi['labAnaTarget'].SetLabel('No valid source-info yet')
            infost = 'Upgrade-preparation:  \n' + \
                    '- install the latest version of knobjex \n' + \
                    '- create a new db (menu file: new database) with it \n' + \
                    '- this latest versioned database will be the new target-db \n' + \
                    'for your old data \n\n' + \
                    'Normal steps:  \n' + \
                    '- backup source- and target-databases \n' + \
                    '- choose import-type \n' + \
                    '- select the files \n' + \
                    '- probe the databases for version-info \n' + \
                    '(for older dbs (< 102.02) db-version = 0)   \n' + \
                    '- set the conditions  \n' + \
                    '- and transfer the data (import)!'
            self.ctrldi['labStatus'].SetLabel(infost)

        elif importtypest == 'Text-file':

            self.showControlList(databasesetli, False)
            self.showControlList(textfilesetli, True)

            self.ctrldi['labSource'].SetLabel('Source-text-file:')
            self.ctrldi['butAnalyse'].SetLabel('Probe text-file')

            self.ctrldi['labAnaSource'].SetLabel(
                    'Probe to see popup')
            self.ctrldi['labAnaTarget'].SetLabel(
                    'Currently opened database')
            infost = 'Procedure:\n\n' + \
                '- Select your import-text-file\n' + \
                '- probe it; make sure:\n' +\
                '  * you have the right column-separator (two underscores "__" on default)\n' + \
                '  * col-width Object1 = col-width Object2\n' + \
                '  (or you tree-links may be broken)\n' + \
                '- add import-parameters to identify the import\n\n' +\
                '- Hit button import\n\n' + \
                'File-lines will be imported to the current db.'

            self.ctrldi['labStatus'].SetLabel(infost)

##            if self.ctrlNameIs(c,'cboObject'):
##                self.readCurrentObject()

    def getSourceFile(self):
        return os.path.normpath(self.ctrldi['txtSource'].Value)

    def getTargetFile(self):
        return os.path.normpath(self.ctrldi['txtTarget'].Value)

    def openFile(self, importtypest):

        if importtypest == 'Database':
            dlg = wx.FileDialog(
                self, message="Choose your database (*.db*)",
                defaultDir=os.getcwd(),
                defaultFile="",
                wildcard="db files (*.db*)|*.db*|all files (*.*)|*.*",
                style=wx.OPEN | wx.CHANGE_DIR | wx.FD_FILE_MUST_EXIST
                )
        elif importtypest == 'Text-file':
            dlg = wx.FileDialog(
                self, message="Choose your text-file (knobjex*.txt)",
                defaultDir=knob_logic.readOption('export_folder_path'),
                defaultFile="",
                wildcard="special txt files (knobjex*.txt)|knobjex*.txt|all files (*.*)|*.*",
                style=wx.OPEN | wx.CHANGE_DIR | wx.FD_FILE_MUST_EXIST
                )

        pathst = ''
        if dlg.ShowModal() == wx.ID_OK:
            pathst = dlg.GetPath()
            print pathst
        dlg.Destroy()
        return pathst

    def checkControlsFilled(self):
        pass


class thruportDialog(wx.Dialog):
    '''
    UNIT INFO:
    This is a dialog-container for the thruport-panel.
    Auto-fits to the controls set on the panel.
    '''

    def __init__ (self, parent, ID, title="",
            pos=wx.DefaultPosition,
            size=wx.DefaultSize, style = wx.DEFAULT_DIALOG_STYLE):
        wx.Dialog.__init__(self, parent, ID, title, pos, size, style)

        pan = thruportPanel(self, -1,
            controlsDefDict = defDialogdi['thruportPanel'])

        # wx.dialog does not autosize panels aot frames
        sizer = wx.BoxSizer(wx.VERTICAL)
        sizer.Add(pan, 1, wx.EXPAND|wx.ALL, 5)
        self.SetSizer(sizer)
        sizer.Fit(self)     # shrink dialog-size to minimal


class thruportPanel(genFrames.genPanel1):
    '''
    UNIT INFO:
    -transfer data from source x to target y

    ADAP HIS
    -adapt port-functions to simple names
    >function doSequence:
        v-get and execute Sequence
        >-set the Sequence (load the cbo)
    -implement derived p-functions
    -impl. status-stuff
    -change the toolbar-button

    ADAP NO
    '''


    def __init__(self, parent, ID, pos = wx.DefaultPosition,
            size = wx.DefaultSize, controlsDefDict = None ):
        genFrames.genPanel1.__init__(self, parent,ID, pos,
            size, controlsDefDict)
        self.parent = parent
        self.loadData()

    def loadData(self):
        self.ctrldi['labFolderPathVal'].SetLabel(
            knob_logic.readOption('thruport_folder_path'))

        sequencesli = [
                        'Set all exchanges -- 1,2,3,4,5,6',
                        'Set all exchanges, no overwrite -- 1,2,3,4,5,0',
                        'Set all imports -- 1,2,3,0,0,4',
                        'Set all imports, no overwrite -- 1,2,3,0,0,0',
                        'Set all exports -- 0,0,0,1,2,3'
                        ]

        self.ctrldi['cboSetActions'].AppendItems(sequencesli)
        self.ctrldi['cboSetActions'].SetSelection(0)
        self.ctrldi['labStatus'].SetForegroundColour(wx.BLUE)
        self.ctrldi['labStatus'].SetLabel(
            'This dialog lets you exchange special text-files \n' + \
            'to use with you mobile device. Thus you can import items \n' + \
            '(appointments, ideas) and export your calendar and projects.\n\n' + \
            'Set the desired exchange-sequence and ' + \
            'execute when ready...\n\n\n\n\n\n\n\n\n\n')
        self.ctrldi['butDoActions'].SetFocus()

##        fillComboData(cboIF, 'db_params', ['Strings'],
##            {'strings':{'Name':'import-file-path-list'}})
####        cboIF.AppendItems(comboli)
##        cboIF.SetSelection(0)

        septypeli = ['sep-current-os', 'sep-windows', 'sep-linux-or-newmac', 
                        'sep-oldmac']
        self.ctrldi['cboLineSep'].AppendItems(septypeli)
        self.ctrldi['cboLineSep'].SetSelection(1)


    def doSequence(self, actiontypest, newsequenceli=[]):
        '''
        UNIT INFO
        -get the sequence-data from the txtcontrols and execute the
        belonging functions in order
        -set the textcontrols based on the newly input sequence
        '''

        self.writeStatus('', False)
        messageli = [
        '>  importing changes from previous multi-branche-list...',
        '>  importing changes from previous tasklist...',
        '>  importing new tree-items from import-file...',
        '>  exporting new multibranche-list...',
        '>  exporting new task-list...',
        '>  creating new import-file-template...'
        ]

        controlli = ['txtImChaBranche','txtImChaTask','txtImFile',
                        'txtExBranche','txtExTask','txtNewImFile']
        functionli=[]   # create below on basis of controlli: txt > fun
        sequenceli = []

        if actiontypest == 'get-and-execute':
            # sequence = control
            for ctrlst in controlli:
                sequenceli.append(int(self.ctrldi[ctrlst].Value))
                functionst = 'fun' + ctrlst[3:]
                functionli.append(functionst)

##            print sequenceli
##            print functionli

            for n in range(1,len(controlli)+1):
                if n in sequenceli:
                    indexit = sequenceli.index(n)
##                    print functionli[indexit]
                    self.writeStatus(messageli[indexit])
                    try:
                        getattr(self, functionli[indexit])()
                        self.writeStatus('OK',True, False)
                    except:
                        errormest = str(sys.exc_info()[1])
                        self.writeStatus( errormest)
            self.writeStatus('\nExchange-sequence completed.')

        elif actiontypest == 'set':
            # control = sequence
            for ctrlst in controlli:
                m = controlli.index(ctrlst)
                self.ctrldi[ctrlst].Value = str(newsequenceli[m])

    def writeStatus(self, statustextst, appendbo=True, addlinebreakbo=True):
        if appendbo:
            oldstatusst = self.ctrldi['labStatus'].GetLabel()
            if addlinebreakbo:
                newstatusst = oldstatusst + '\n' + statustextst
            else:
                newstatusst = oldstatusst + statustextst
            self.ctrldi['labStatus'].SetLabel(newstatusst)
        else:
            self.ctrldi['labStatus'].SetLabel(statustextst)


    def funImChaBranche(self):
        thruport.importChangesFromExportFiles(knob_logic.readOption('thruport_folder_path'),
                                            knob_logic.readOption('export_branches_file_name'))

    def funImChaTask(self):
        thruport.importChangesFromExportFiles(knob_logic.readOption('thruport_folder_path'),
                                            knob_logic.readOption('export_tasks_file_name'))

    def funImFile(self):
        thruport.importTreeFile(knob_logic.readOption('thruport_folder_path'),
                                knob_logic.readOption('import_file_name'),
                                self.ctrldi['cboLineSep'].Value)

    def funExBranche(self):
        thruport.exportDataToFile('FDQ_RELS_MULTIBRANCHE_EXPORT',
                                knob_logic.readOption('thruport_folder_path'),
                                knob_logic.readOption('export_branches_file_name'),
                                self.ctrldi['cboLineSep'].Value)

    def funExTask(self):
        thruport.exportDataToFile('FDQ_RELS_TASKS_EXPORT',
                                knob_logic.readOption('thruport_folder_path'),
                                knob_logic.readOption('export_tasks_file_name'),
                                self.ctrldi['cboLineSep'].Value)

    def funNewImFile(self):
        thruport.exportDataToFile('FDQ_RELATIONS_EXPORTABLE',
                                knob_logic.readOption('thruport_folder_path'),
                                knob_logic.readOption('import_file_name'),
                                self.ctrldi['cboLineSep'].Value)

    def onAnyEvent(self, evt):
        t = evt.GetEventType()
        c = evt.GetId()
        try:
            if self.evtTypeIs(t,'BUTTON'):
                if self.ctrlNameIs(c,'butDoActions'):
                    self.doSequence('get-and-execute')
                elif self.ctrlNameIs(c,'butBack'):
                    pass

            elif self.evtTypeIs(t,'TEXT'):
                pass
            elif self.evtTypeIs(t,'TEXT_COPY'):
                pass
            elif self.evtTypeIs(t,'TEXT_ENTER'):
                pass
    ##            if self.ctrlNameIs(c,'txtSeek'):
    ##                txt = self.ctrldi['txtSeek']
    ##                cbo = self.ctrldi['cboObject']
    ##                wx.SetCursor(wx.HOURGLASS_CURSOR)
    ##                cbo.Clear()
    ##                fillComboData(cbo, 'Objects',['Object'],
    ##                        {'subs':{'Object': txt.Value}})
    ##                wx.SetCursor(wx.STANDARD_CURSOR)
            elif self.evtTypeIs(t,'COMBOBOX'):
                if self.ctrlNameIs(c,'cboSetActions'):
                    valst = self.ctrldi['cboSetActions'].Value
                    print valst
                    rawsequencest = valst.split(" -- ")[1]
                    sequenceli = rawsequencest.split(',')
                    print rawsequencest
                    print sequenceli
                    self.doSequence('set', sequenceli)
        except:
            customst = 'The operation could not be completed.'
            messagest = customst +  '\n\n' + str(sys.exc_info()[0])+ \
             '\n' + str(sys.exc_info()[1])
            print messagest
            showMessage(self,messagest,'Error',wx.ICON_WARNING)
            messt = 'Thruport failed. Please investigate and retry when ready...'
            self.ctrldi['labStatus'].SetLabel(messt)


class recentDbDialog(wx.Dialog):
    '''
    UNIT INFO:
    Dialog to select a previously openened database
    '''

    def __init__ (self, parent, ID, title="",
            pos=wx.DefaultPosition,size=wx.DefaultSize, 
            style = wx.DEFAULT_DIALOG_STYLE | wx.RESIZE_BORDER):
        wx.Dialog.__init__(self, parent, ID, title, pos, size, style)

        self.parent = parent

        pan = recentDbPanel(self, -1,
            controlsDefDict = defDialogdi['recentDbPanel'])

        # wx.dialog does not autosize panels aot frames
        sizer = wx.BoxSizer(wx.VERTICAL)
        sizer.Add(pan, 1, wx.EXPAND|wx.ALL, 5)
        self.SetSizer(sizer)
        sizer.Fit(self)     # shrink dialog-size to minimal


class recentDbPanel(genFrames.genPanel1):
    '''
    UNIT INFO:
    Panel to select a previously openened database

    ADAP HIS

    ADAP NO
    '''

    def __init__(self, parent, ID, pos = wx.DefaultPosition,
            size = wx.DefaultSize, controlsDefDict = None ):
        genFrames.genPanel1.__init__(self, parent,ID, pos,
            size, controlsDefDict)
        self.parent = parent
        
##        lstBoxDbs = self.ctrldi['lstDbs']
##        labLabStatus = self.ctrldi['labStatus']
##        butButOpen = self.ctrldi['butOpenDb']
##        # wx.dialog does not autosize panels aot frames
##        sizer = wx.BoxSizer(wx.HORIZONTAL)
##        sizer.Add( lstBoxDbs , 1, wx.EXPAND|wx.ALL, 5)
##        self.SetSizer(sizer)
##        sizer.Fit(self)     # shrink dialog-size to minimal
                
        self.loadData()

    def loadData(self):
        # ophalen string
        multipathst = knob_logic.readOption('previous_db_paths', 'sys')
        # verlijsten
        multipathli = multipathst.split(';;')
        print multipathli
        self.ctrldi['lstDbs'].InsertItems(multipathli,0)
        
    def onAnyEvent(self, evt):
        t = evt.GetEventType()
        c = evt.GetId()
        try:
            if self.evtTypeIs(t,'BUTTON'):
                if self.ctrlNameIs(c,'butOpenDb'):
                    chosendbst = self.ctrldi['lstDbs'].GetStringSelection()
                    self.parent.parent.loadDatabase(chosendbst)
                    self.parent.Destroy()

            elif self.evtTypeIs(t,'TEXT'):
                pass
            elif self.evtTypeIs(t,'TEXT_COPY'):
                pass
            elif self.evtTypeIs(t,'TEXT_ENTER'):
                pass
            elif self.evtTypeIs(t,'COMBOBOX'):
                pass
            elif self.evtTypeIs(t,'LISTBOX'):
                if self.ctrlNameIs(c,'lstDbs'):
                    print 'listbox'
                    chosendbst = self.ctrldi['lstDbs'].GetStringSelection()
                    dbnamest = os.path.basename(chosendbst)
                    self.ctrldi['labStatus'].SetLabel(dbnamest)
                    

        except:
##            customst = 'The operation could not be completed.'
            messagest = str(sys.exc_info()[0])+ \
             '\n' + str(sys.exc_info()[1])
            print messagest
            showMessage(self,messagest,'Error',wx.ICON_WARNING)
##            raise


class longTextPanel(genFrames.genPanel1):
    '''
    ADAP HIS

    ADAP NO

    '''

    def __init__(self, parent, ID, pos = wx.DefaultPosition,
            size = wx.DefaultSize, controlsDefDict = None ):
        genFrames.genPanel1.__init__(self, parent,ID, pos,
            size, controlsDefDict)
        self.parent = parent
        
        self.ltext = self.ctrldi['txtLongText']

        # sizing
        self.hbox = wx.BoxSizer(wx.HORIZONTAL)
        self.hbox.Add(self.ltext, 1, wx.EXPAND)
        self.SetSizer(self.hbox)
        

    def onAnyEvent(self, evt):
        t = evt.GetEventType()
        c = evt.GetId()

        if self.evtTypeIs(t,'BUTTON'):
            if self.ctrlNameIs(c,'butSave'):
                self.updateOption()
        elif self.evtTypeIs(t,'TEXT'):
            pass
        elif self.evtTypeIs(t,'TEXT_COPY'):
            pass
        elif self.evtTypeIs(t,'TEXT_ENTER'):
            if self.ctrlNameIs(c,'txtSeek'):
                pass
        elif self.evtTypeIs(t,'COMBOBOX'):
            pass
        if self.evtTypeIs(t,'LISTBOX'):
            if self.ctrlNameIs(c,'lstQuery'):
                pass


class TestPanel(wx.Panel):
    def __init__(self, parent, log):
        self.log = log
        wx.Panel.__init__(self, parent, -1)
        b = wx.Button(self, -1, "Show the wx.aui Demo Frame", (50,50))
        self.Bind(wx.EVT_BUTTON, self.OnButton, b)

    def OnButton(self, evt):
        frame = PyAUIFrame(self, wx.ID_ANY, "wx.aui wxPython Demo", size=(750, 590))
        frame.Show()

class myApp(wx.App):
    def OnInit(self):
        myFrame = PyAUIFrame(None, wx.ID_ANY, "Knobjex InfoManager",(10,10), size=(1050, 700))
        myFrame.Show(1)
        self.SetTopWindow(myFrame)
        return True

if __name__ == '__main__':
    app = myApp(0)
    app.MainLoop()

